Changes in / [c39544a:da55d5b] in mainline
- Location:
- uspace
- Files:
-
- 4 deleted
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbkbd/usbkbd.ma
rc39544a rda55d5b 1 1 10 usb&class=hid 2 10 usb&hid -
uspace/lib/drv/generic/remote_usbhc.c
rc39544a rda55d5b 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 *);45 44 static void remote_usbhc_get_buffer(device_t *, void *, ipc_callid_t, ipc_call_t *); 46 45 static void remote_usbhc_interrupt_out(device_t *, void *, ipc_callid_t, ipc_call_t *); 47 46 static void remote_usbhc_interrupt_in(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 *); 47 //static void remote_usb(device_t *, void *, ipc_callid_t, ipc_call_t *); 55 48 56 49 /** Remote USB interface operations. */ 57 50 static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = { 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 51 &remote_usbhc_get_buffer, 52 &remote_usbhc_interrupt_out, 53 &remote_usbhc_interrupt_in 68 54 }; 69 55 … … 82 68 } async_transaction_t; 83 69 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 }104 70 105 71 void remote_usbhc_get_buffer(device_t *device, void *iface, … … 159 125 } 160 126 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 } 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; 176 131 177 132 size_t expected_len = IPC_GET_ARG3(*call); … … 194 149 } 195 150 151 if (!usb_iface->interrupt_out) { 152 ipc_answer_0(callid, ENOTSUP); 153 return; 154 } 155 196 156 async_transaction_t *trans = malloc(sizeof(async_transaction_t)); 197 157 trans->caller = callid; 198 trans->buffer = buffer;199 trans->size = len;200 201 int rc = transfer_func(device, target, buffer, len,158 trans->buffer = NULL; 159 trans->size = 0; 160 161 int rc = usb_iface->interrupt_out(device, target, buffer, len, 202 162 callback_out, trans); 203 163 204 164 if (rc != EOK) { 205 165 ipc_answer_0(callid, rc); 206 if (buffer != NULL) {207 free(buffer);208 }209 166 free(trans); 210 167 } 211 168 } 212 169 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 } 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; 228 174 229 175 size_t len = IPC_GET_ARG3(*call); … … 233 179 }; 234 180 181 if (!usb_iface->interrupt_in) { 182 ipc_answer_0(callid, ENOTSUP); 183 return; 184 } 185 235 186 async_transaction_t *trans = malloc(sizeof(async_transaction_t)); 236 187 trans->caller = callid; … … 238 189 trans->size = len; 239 190 240 int rc = transfer_func(device, target, trans->buffer, len,191 int rc = usb_iface->interrupt_in(device, target, trans->buffer, len, 241 192 callback_in, trans); 242 193 … … 248 199 } 249 200 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 399 201 400 202 /** -
uspace/lib/drv/include/usbhc_iface.h
rc39544a rda55d5b 92 92 */ 93 93 typedef enum { 94 /** Tell USB address assigned to device.95 * Parameters:96 * - devman handle id97 * Answer:98 * - EINVAL - unknown handle or handle not managed by this driver99 * - ENOTSUP - operation not supported by HC (shall not happen)100 * - arbitrary error code if returned by remote implementation101 * - EOK - handle found, first parameter contains the USB address102 */103 IPC_M_USBHC_GET_ADDRESS,104 105 94 /** Asks for data buffer. 106 95 * See explanation at usb_iface_funcs_t. … … 166 155 usb_transaction_outcome_t, size_t, void *); 167 156 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 182 157 /** USB devices communication interface. */ 183 158 typedef struct { 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, 159 int (*interrupt_out)(device_t *, usb_target_t, 160 void *, size_t, 161 usbhc_iface_transfer_out_callback_t, void *); 162 int (*interrupt_in)(device_t *, usb_target_t, 163 void *, size_t, 192 164 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,197 usbhc_iface_transfer_out_callback_t, void *);198 165 } usbhc_iface_t; 199 166 -
uspace/lib/usb/Makefile
rc39544a rda55d5b 34 34 SOURCES = \ 35 35 src/hcdhubd.c \ 36 src/hcdrv.c \37 src/hubdrv.c \38 36 src/localdrv.c \ 39 src/remotedrv.c \40 37 src/usb.c \ 41 38 src/usbdrv.c -
uspace/lib/usb/include/usb/hcdhubd.h
rc39544a rda55d5b 37 37 38 38 #include <adt/list.h> 39 #include <bool.h>40 39 #include <driver.h> 41 40 #include <usb/usb.h> … … 176 175 int usb_hc_async_wait_for(usb_handle_t); 177 176 178 int usb_hc_add_child_device(device_t *, const char *, const char *, bool);179 177 180 178 #endif -
uspace/lib/usb/include/usb/usbdrv.h
rc39544a rda55d5b 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 64 50 int usb_drv_async_wait_for(usb_handle_t); 65 51 -
uspace/lib/usb/src/hcdhubd.c
rc39544a rda55d5b 31 31 */ 32 32 /** @file 33 * @brief Common stuff for both HC driver and hub driver.33 * @brief HC driver and hub driver (implementation). 34 34 */ 35 35 #include <usb/hcdhubd.h> … … 40 40 #include <bool.h> 41 41 #include <errno.h> 42 #include <str_error.h>43 42 #include <usb/classes/hub.h> 44 43 45 #include "hcdhubd_private.h" 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 } 46 151 47 152 /** Callback when new device is detected and must be handled by this driver. 48 153 * 49 154 * @param dev New device. 50 * @return Error code. 155 * @return Error code.hub added, hurrah!\n" 51 156 */ 52 157 static int add_device(device_t *dev) { 158 /* 159 * FIXME: use some magic to determine whether hub or another HC 160 * was connected. 161 */ 53 162 bool is_hc = str_cmp(dev->name, USB_HUB_DEVICE_NAME) != 0; 54 163 printf("%s: add_device(name=\"%s\")\n", hc_driver->name, dev->name); … … 58 167 * We are the HC itself. 59 168 */ 60 return usb_add_hc_device(dev); 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 183 /* 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 61 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 62 238 /* 63 * We are some ( maybedeeply nested) hub.239 * We are some (probably deeply nested) hub. 64 240 * Thus, assign our own operations and explore already 65 241 * connected devices. 66 242 */ 67 return usb_add_hub_device(dev); 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 } 68 370 } 69 371 } … … 89 391 hc_driver = hc; 90 392 hc_driver_generic.name = hc->name; 393 394 /* 395 * Launch here fibril that will periodically check all 396 * attached hubs for status change. 397 * WARN: This call will effectively do nothing. 398 */ 399 check_hub_changes(); 91 400 92 401 /* … … 105 414 * @return Error code. 106 415 */ 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; 416 int usb_hcd_add_root_hub(usb_hc_device_t *dev) { 135 417 int rc; 136 418 137 device_t *child = create_device(); 419 /* 420 * Announce presence of child device. 421 */ 422 device_t *hub = NULL; 138 423 match_id_t *match_id = NULL; 139 424 140 if (child == NULL) { 425 hub = create_device(); 426 if (hub == NULL) { 141 427 rc = ENOMEM; 142 428 goto failure; 143 429 } 144 child->name = child_info->name;430 hub->name = USB_HUB_DEVICE_NAME; 145 431 146 432 match_id = create_match_id(); … … 149 435 goto failure; 150 436 } 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 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); 161 451 if (rc != EOK) { 162 452 goto failure; 163 453 } 164 454 165 goto leave; 455 printf("%s: registered root hub\n", dev->generic->name); 456 return EOK; 166 457 167 458 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); 180 return EOK; 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; 459 if (hub != NULL) { 460 hub->name = NULL; 461 delete_device(hub); 462 } 463 delete_match_id(match_id); 464 465 return rc; 231 466 } 232 467 -
uspace/lib/usb/src/usbdrv.c
rc39544a rda55d5b 64 64 * Call parent hub to obtain device handle of respective HC. 65 65 */ 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; 66 return ENOTSUP; 81 67 } 82 68 … … 89 75 usb_address_t usb_drv_get_my_address(int phone, device_t *dev) 90 76 { 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; 77 return ENOTSUP; 100 78 } 101 79 … … 345 323 } 346 324 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 417 325 /** 418 326 * @}
Note:
See TracChangeset
for help on using the changeset viewer.