Changeset 5994cc3 in mainline for uspace/lib/usbhost/src/hcd.c
- Timestamp:
- 2012-12-16T20:08:54Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 9c7ed9c
- Parents:
- ddab093
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usbhost/src/hcd.c
rddab093 r5994cc3 36 36 #include <errno.h> 37 37 #include <str_error.h> 38 #include <usb_iface.h> 38 39 #include <usb/debug.h> 39 40 40 41 #include <usb/host/hcd.h> 42 43 typedef struct hc_dev { 44 ddf_fun_t *hc_fun; 45 ddf_fun_t *rh_fun; 46 } hc_dev_t; 47 48 static hc_dev_t *dev_to_hc_dev(ddf_dev_t *dev) 49 { 50 return ddf_dev_data_get(dev); 51 } 52 53 hcd_t *dev_to_hcd(ddf_dev_t *dev) 54 { 55 hc_dev_t *hc_dev = dev_to_hc_dev(dev); 56 if (!hc_dev || !hc_dev->hc_fun) { 57 usb_log_error("Invalid OHCI device.\n"); 58 return NULL; 59 } 60 return ddf_fun_data_get(hc_dev->hc_fun); 61 } 62 63 typedef struct usb_dev { 64 usb_address_t address; 65 usb_speed_t speed; 66 devman_handle_t handle; 67 } usb_dev_t; 68 69 /** Get USB address assigned to root hub. 70 * 71 * @param[in] fun Root hub function. 72 * @param[out] address Store the address here. 73 * @return Error code. 74 */ 75 static int rh_get_my_address(ddf_fun_t *fun, usb_address_t *address) 76 { 77 assert(fun); 78 if (address != NULL) { 79 usb_dev_t *usb_dev = ddf_fun_data_get(fun); 80 *address = usb_dev->address; 81 } 82 return EOK; 83 } 84 85 /** Gets handle of the respective hc (this device, hc function). 86 * 87 * @param[in] root_hub_fun Root hub function seeking hc handle. 88 * @param[out] handle Place to write the handle. 89 * @return Error code. 90 */ 91 static int rh_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle) 92 { 93 assert(fun); 94 95 if (handle != NULL) { 96 usb_dev_t *usb_dev = ddf_fun_data_get(fun); 97 *handle = usb_dev->handle; 98 } 99 return EOK; 100 } 101 102 /** Root hub USB interface */ 103 static usb_iface_t usb_iface = { 104 .get_hc_handle = rh_get_hc_handle, 105 .get_my_address = rh_get_my_address, 106 }; 107 /** Standard USB RH options (RH interface) */ 108 static ddf_dev_ops_t rh_ops = { 109 .interfaces[USB_DEV_IFACE] = &usb_iface, 110 }; 111 112 /** Standard USB HC options (HC interface) */ 113 static ddf_dev_ops_t hc_ops = { 114 .interfaces[USBHC_DEV_IFACE] = &hcd_iface, 115 }; 41 116 42 117 /** Announce root hub to the DDF … … 46 121 * @return Error code 47 122 */ 48 int hcd_ register_hub(hcd_t *instance, usb_address_t *address, ddf_fun_t *hub_fun)123 int hcd_setup_hub(hcd_t *instance, usb_address_t *address, ddf_dev_t *device) 49 124 { 50 125 assert(instance); 51 126 assert(address); 52 assert(hub_fun); 53 54 int ret = usb_device_manager_request_address( 55 &instance->dev_manager, address, false, 56 USB_SPEED_FULL); 127 assert(device); 128 129 hc_dev_t *hc_dev = ddf_dev_data_get(device); 130 hc_dev->rh_fun = ddf_fun_create(device, fun_inner, "rh"); 131 if (!hc_dev->rh_fun) 132 return ENOMEM; 133 usb_dev_t *rh = ddf_fun_data_alloc(hc_dev->rh_fun, sizeof(usb_dev_t)); 134 if (!rh) { 135 ddf_fun_destroy(hc_dev->rh_fun); 136 return ENOMEM; 137 } 138 139 140 int ret = usb_device_manager_request_address(&instance->dev_manager, 141 address, false, USB_SPEED_FULL); 57 142 if (ret != EOK) { 58 143 usb_log_error("Failed to get root hub address: %s\n", 59 144 str_error(ret)); 145 ddf_fun_destroy(hc_dev->rh_fun); 60 146 return ret; 61 147 } 148 149 rh->address = *address; 150 rh->speed = USB_SPEED_FULL; 151 rh->handle = ddf_fun_get_handle(hc_dev->hc_fun); 152 153 ddf_fun_set_ops(hc_dev->rh_fun, &rh_ops); 62 154 63 155 #define CHECK_RET_UNREG_RETURN(ret, message...) \ … … 69 161 usb_device_manager_release_address( \ 70 162 &instance->dev_manager, *address); \ 163 ddf_fun_destroy(hc_dev->rh_fun); \ 71 164 return ret; \ 72 165 } else (void)0 … … 80 173 str_error(ret)); 81 174 82 ret = ddf_fun_add_match_id(h ub_fun, "usb&class=hub", 100);175 ret = ddf_fun_add_match_id(hc_dev->rh_fun, "usb&class=hub", 100); 83 176 CHECK_RET_UNREG_RETURN(ret, 84 177 "Failed to add root hub match-id: %s.\n", str_error(ret)); 85 178 86 ret = ddf_fun_bind(h ub_fun);179 ret = ddf_fun_bind(hc_dev->rh_fun); 87 180 CHECK_RET_UNREG_RETURN(ret, 88 181 "Failed to bind root hub function: %s.\n", str_error(ret)); 89 182 90 183 ret = usb_device_manager_bind_address(&instance->dev_manager, 91 *address, ddf_fun_get_handle(h ub_fun));184 *address, ddf_fun_get_handle(hc_dev->rh_fun)); 92 185 if (ret != EOK) 93 186 usb_log_warning("Failed to bind root hub address: %s.\n", 94 187 str_error(ret)); 95 188 189 96 190 return EOK; 97 191 #undef CHECK_RET_UNREG_RETURN 192 } 193 194 /** Initialize hc structures. 195 * 196 * @param[in] device DDF instance of the device to use. 197 * 198 * This function does all the preparatory work for hc driver implementation. 199 * - gets device hw resources 200 * - disables OHCI legacy support 201 * - asks for interrupt 202 * - registers interrupt handler 203 */ 204 int hcd_setup_device(ddf_dev_t *device) 205 { 206 if (device == NULL) 207 return EBADMEM; 208 209 hc_dev_t *instance = ddf_dev_data_alloc(device, sizeof(hc_dev_t)); 210 if (instance == NULL) { 211 usb_log_error("Failed to allocate OHCI driver.\n"); 212 return ENOMEM; 213 } 214 215 #define CHECK_RET_DEST_FREE_RETURN(ret, message...) \ 216 if (ret != EOK) { \ 217 if (instance->hc_fun) { \ 218 ddf_fun_destroy(instance->hc_fun); \ 219 } \ 220 usb_log_error(message); \ 221 return ret; \ 222 } else (void)0 223 224 instance->hc_fun = ddf_fun_create(device, fun_exposed, "hc"); 225 int ret = instance->hc_fun ? EOK : ENOMEM; 226 CHECK_RET_DEST_FREE_RETURN(ret, 227 "Failed to create OHCI HC function: %s.\n", str_error(ret)); 228 ddf_fun_set_ops(instance->hc_fun, &hc_ops); 229 hcd_t *hcd = ddf_fun_data_alloc(instance->hc_fun, sizeof(hcd_t)); 230 ret = hcd ? EOK : ENOMEM; 231 CHECK_RET_DEST_FREE_RETURN(ret, 232 "Failed to allocate HCD structure: %s.\n", str_error(ret)); 233 234 hcd_init(hcd, USB_SPEED_FULL, BANDWIDTH_AVAILABLE_USB11, 235 bandwidth_count_usb11); 236 237 ret = ddf_fun_bind(instance->hc_fun); 238 CHECK_RET_DEST_FREE_RETURN(ret, 239 "Failed to bind OHCI device function: %s.\n", str_error(ret)); 240 241 #define CHECK_RET_UNBIND_FREE_RETURN(ret, message...) \ 242 if (ret != EOK) { \ 243 ddf_fun_unbind(instance->hc_fun); \ 244 CHECK_RET_DEST_FREE_RETURN(ret, \ 245 "Failed to add OHCI to HC class: %s.\n", str_error(ret)); \ 246 } else (void)0 247 ret = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY); 248 CHECK_RET_UNBIND_FREE_RETURN(ret, 249 "Failed to add hc to category: %s\n", str_error(ret)); 250 251 /* HC should be ok at this point (except it can't do anything) */ 252 253 return EOK; 98 254 } 99 255
Note:
See TracChangeset
for help on using the changeset viewer.