Changeset 00aece0 in mainline for uspace/lib/usbhost/src/usb_device_manager.c
- Timestamp:
- 2012-02-18T16:47:38Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 4449c6c
- Parents:
- bd5f3b7 (diff), f943dd3 (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. - File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usbhost/src/usb_device_manager.c
rbd5f3b7 r00aece0 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 29 28 /** @addtogroup libusbhost 30 29 * @{ 31 30 */ 32 31 /** @file 33 * Device keeper structure and functions (implementation).32 * Device manager structure and functions (implementation). 34 33 */ 35 34 #include <assert.h> 36 35 #include <errno.h> 37 36 #include <usb/debug.h> 38 #include <usb/host/device_keeper.h> 39 40 /*----------------------------------------------------------------------------*/ 41 /** Initialize device keeper structure. 37 #include <usb/host/usb_device_manager.h> 38 39 /** Get a free USB address 40 * 41 * @param[in] instance Device manager structure to use. 42 * @return Free address, or error code. 43 */ 44 static usb_address_t usb_device_manager_get_free_address( 45 usb_device_manager_t *instance) 46 { 47 48 usb_address_t new_address = instance->last_address; 49 do { 50 new_address = (new_address + 1) % USB_ADDRESS_COUNT; 51 if (new_address == USB_ADDRESS_DEFAULT) 52 new_address = 1; 53 if (new_address == instance->last_address) { 54 return ENOSPC; 55 } 56 } while (instance->devices[new_address].occupied); 57 58 assert(new_address != USB_ADDRESS_DEFAULT); 59 instance->last_address = new_address; 60 61 return new_address; 62 } 63 /*----------------------------------------------------------------------------*/ 64 /** Initialize device manager structure. 42 65 * 43 66 * @param[in] instance Memory place to initialize. 67 * @param[in] max_speed Maximum allowed USB speed of devices (inclusive). 44 68 * 45 69 * Set all values to false/0. 46 70 */ 47 void usb_device_ keeper_init(usb_device_keeper_t *instance)48 { 49 assert(instance); 50 unsigned i = 0;51 for ( ; i < USB_ADDRESS_COUNT; ++i) {71 void usb_device_manager_init( 72 usb_device_manager_t *instance, usb_speed_t max_speed) 73 { 74 assert(instance); 75 for (unsigned i = 0; i < USB_ADDRESS_COUNT; ++i) { 52 76 instance->devices[i].occupied = false; 53 77 instance->devices[i].handle = 0; 54 78 instance->devices[i].speed = USB_SPEED_MAX; 55 79 } 56 // TODO: is this hack enough? 57 // (it is needed to allow smooth registration at default address) 58 instance->devices[0].occupied = true; 59 instance->last_address = 0; 80 instance->last_address = 1; 81 instance->max_speed = max_speed; 60 82 fibril_mutex_initialize(&instance->guard); 61 83 } 62 84 /*----------------------------------------------------------------------------*/ 63 /** Get a free USB address 64 * 65 * @param[in] instance Device keeper structure to use. 66 * @param[in] speed Speed of the device requiring address. 67 * @return Free address, or error code. 68 */ 69 usb_address_t device_keeper_get_free_address( 70 usb_device_keeper_t *instance, usb_speed_t speed) 71 { 72 assert(instance); 73 fibril_mutex_lock(&instance->guard); 74 75 usb_address_t new_address = instance->last_address; 76 do { 77 ++new_address; 78 if (new_address > USB11_ADDRESS_MAX) 79 new_address = 1; 80 if (new_address == instance->last_address) { 85 /** Request USB address. 86 * @param instance usb_device_manager 87 * @param address Pointer to requested address value, place to store new address 88 * @parma strict Fail if the requested address is not available. 89 * @return Error code. 90 * @note Default address is only available in strict mode. 91 */ 92 int usb_device_manager_request_address(usb_device_manager_t *instance, 93 usb_address_t *address, bool strict, usb_speed_t speed) 94 { 95 assert(instance); 96 assert(address); 97 if (speed > instance->max_speed) 98 return ENOTSUP; 99 100 if ((*address) < 0 || (*address) >= USB_ADDRESS_COUNT) 101 return EINVAL; 102 103 fibril_mutex_lock(&instance->guard); 104 /* Only grant default address to strict requests */ 105 if (( (*address) == USB_ADDRESS_DEFAULT) && !strict) { 106 *address = instance->last_address; 107 } 108 109 if (instance->devices[*address].occupied) { 110 if (strict) { 81 111 fibril_mutex_unlock(&instance->guard); 82 return ENO SPC;112 return ENOENT; 83 113 } 84 } while (instance->devices[new_address].occupied);85 86 assert( new_address != USB_ADDRESS_DEFAULT);87 assert(instance->devices[ new_address].occupied == false);88 89 instance->devices[new_address].occupied = true; 90 instance->devices[ new_address].speed = speed;91 instance-> last_address = new_address;92 93 fibril_mutex_unlock(&instance->guard); 94 return new_address;114 *address = usb_device_manager_get_free_address(instance); 115 } 116 assert(instance->devices[*address].occupied == false); 117 assert(instance->devices[*address].handle == 0); 118 assert(*address != USB_ADDRESS_DEFAULT || strict); 119 120 instance->devices[*address].occupied = true; 121 instance->devices[*address].speed = speed; 122 123 fibril_mutex_unlock(&instance->guard); 124 return EOK; 95 125 } 96 126 /*----------------------------------------------------------------------------*/ 97 127 /** Bind USB address to devman handle. 98 128 * 99 * @param[in] instance Device keeper structure to use.129 * @param[in] instance Device manager structure to use. 100 130 * @param[in] address Device address 101 131 * @param[in] handle Devman handle of the device. 102 */ 103 void usb_device_keeper_bind(usb_device_keeper_t *instance, 132 * @return Error code. 133 * @note Won't accept binding for default address. 134 */ 135 int usb_device_manager_bind_address(usb_device_manager_t *instance, 104 136 usb_address_t address, devman_handle_t handle) 105 137 { 106 assert(instance); 107 fibril_mutex_lock(&instance->guard); 108 109 assert(address > 0); 110 assert(address <= USB11_ADDRESS_MAX); 111 assert(instance->devices[address].occupied); 112 138 if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) { 139 return EINVAL; 140 } 141 assert(instance); 142 143 fibril_mutex_lock(&instance->guard); 144 /* Not reserved */ 145 if (!instance->devices[address].occupied) { 146 fibril_mutex_unlock(&instance->guard); 147 return ENOENT; 148 } 149 /* Already bound */ 150 if (instance->devices[address].handle != 0) { 151 fibril_mutex_unlock(&instance->guard); 152 return EEXISTS; 153 } 113 154 instance->devices[address].handle = handle; 114 155 fibril_mutex_unlock(&instance->guard); 156 return EOK; 115 157 } 116 158 /*----------------------------------------------------------------------------*/ 117 159 /** Release used USB address. 118 160 * 119 * @param[in] instance Device keeper structure to use.161 * @param[in] instance Device manager structure to use. 120 162 * @param[in] address Device address 121 */ 122 void usb_device_keeper_release( 123 usb_device_keeper_t *instance, usb_address_t address) 124 { 125 assert(instance); 126 assert(address > 0); 127 assert(address <= USB11_ADDRESS_MAX); 128 129 fibril_mutex_lock(&instance->guard); 130 assert(instance->devices[address].occupied); 163 * @return Error code. 164 */ 165 int usb_device_manager_release_address( 166 usb_device_manager_t *instance, usb_address_t address) 167 { 168 if ((address < 0) || (address >= USB_ADDRESS_COUNT)) { 169 return EINVAL; 170 } 171 assert(instance); 172 173 fibril_mutex_lock(&instance->guard); 174 if (!instance->devices[address].occupied) { 175 fibril_mutex_unlock(&instance->guard); 176 return ENOENT; 177 } 131 178 132 179 instance->devices[address].occupied = false; 133 fibril_mutex_unlock(&instance->guard); 134 } 135 /*----------------------------------------------------------------------------*/ 136 /** Find USB address associated with the device 137 * 138 * @param[in] instance Device keeper structure to use. 180 instance->devices[address].handle = 0; 181 fibril_mutex_unlock(&instance->guard); 182 return EOK; 183 } 184 /*----------------------------------------------------------------------------*/ 185 /** Find USB address associated with the device. 186 * 187 * @param[in] instance Device manager structure to use. 139 188 * @param[in] handle Devman handle of the device seeking its address. 140 189 * @return USB Address, or error code. 141 190 */ 142 usb_address_t usb_device_ keeper_find(143 usb_device_ keeper_t *instance, devman_handle_t handle)144 { 145 assert(instance); 146 fibril_mutex_lock(&instance->guard); 147 usb_address_t address = 1;148 while (address <= USB11_ADDRESS_MAX){191 usb_address_t usb_device_manager_find_address( 192 usb_device_manager_t *instance, devman_handle_t handle) 193 { 194 assert(instance); 195 fibril_mutex_lock(&instance->guard); 196 for (usb_address_t address = 1; address <= USB11_ADDRESS_MAX; ++address) 197 { 149 198 if (instance->devices[address].handle == handle) { 150 199 assert(instance->devices[address].occupied); … … 152 201 return address; 153 202 } 154 ++address;155 203 } 156 204 fibril_mutex_unlock(&instance->guard); 157 205 return ENOENT; 158 206 } 159 160 /** Find devman handle assigned to USB address. 161 * Intentionally refuse to find handle of default address. 162 * 163 * @param[in] instance Device keeper structure to use. 207 /*----------------------------------------------------------------------------*/ 208 /** Find devman handle and speed assigned to USB address. 209 * 210 * @param[in] instance Device manager structure to use. 164 211 * @param[in] address Address the caller wants to find. 165 212 * @param[out] handle Where to store found handle. 166 * @return Whether such address is currently occupied. 167 */ 168 bool usb_device_keeper_find_by_address(usb_device_keeper_t *instance, 169 usb_address_t address, devman_handle_t *handle) 170 { 171 assert(instance); 172 fibril_mutex_lock(&instance->guard); 173 if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) { 174 fibril_mutex_unlock(&instance->guard); 175 return false; 176 } 213 * @param[out] speed Assigned speed. 214 * @return Error code. 215 */ 216 int usb_device_manager_get_info_by_address(usb_device_manager_t *instance, 217 usb_address_t address, devman_handle_t *handle, usb_speed_t *speed) 218 { 219 assert(instance); 220 if ((address < 0) || (address >= USB_ADDRESS_COUNT)) { 221 return EINVAL; 222 } 223 224 fibril_mutex_lock(&instance->guard); 177 225 if (!instance->devices[address].occupied) { 178 226 fibril_mutex_unlock(&instance->guard); 179 return false;227 return ENOENT; 180 228 } 181 229 … … 183 231 *handle = instance->devices[address].handle; 184 232 } 185 186 fibril_mutex_unlock(&instance->guard); 187 return true; 188 } 189 190 /*----------------------------------------------------------------------------*/ 191 /** Get speed associated with the address 192 * 193 * @param[in] instance Device keeper structure to use. 194 * @param[in] address Address of the device. 195 * @return USB speed. 196 */ 197 usb_speed_t usb_device_keeper_get_speed( 198 usb_device_keeper_t *instance, usb_address_t address) 199 { 200 assert(instance); 201 assert(address >= 0); 202 assert(address <= USB11_ADDRESS_MAX); 203 204 return instance->devices[address].speed; 233 if (speed != NULL) { 234 *speed = instance->devices[address].speed; 235 } 236 237 fibril_mutex_unlock(&instance->guard); 238 return EOK; 205 239 } 206 240 /**
Note:
See TracChangeset
for help on using the changeset viewer.