Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers EndpointResolver.cpp Source File

EndpointResolver.cpp

00001 /*
00002  * Copyright (c) 2018-2019, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "EndpointResolver.h"
00019 
00020 static uint32_t logical_to_index(uint32_t logical, bool in_not_out)
00021 {
00022     return (logical << 1) | (in_not_out ? 1 : 0);
00023 }
00024 
00025 static uint32_t index_to_logical(uint32_t index)
00026 {
00027     return index >> 1;
00028 }
00029 
00030 
00031 EndpointResolver::EndpointResolver(const usb_ep_table_t *table) : _table(table), _cost(0), _used(0), _valid(true)
00032 {
00033     // Do nothing
00034 }
00035 
00036 EndpointResolver::~EndpointResolver()
00037 {
00038     // Do nothing
00039 }
00040 
00041 void EndpointResolver::endpoint_ctrl(uint32_t size)
00042 {
00043     endpoint_in(USB_EP_TYPE_CTRL, size);
00044     endpoint_out(USB_EP_TYPE_CTRL, size);
00045 }
00046 
00047 usb_ep_t EndpointResolver::next_free_endpoint(bool in_not_out, usb_ep_type_t type, uint32_t size)
00048 {
00049     int index = next_index(type, in_not_out);
00050     if (index < 0) {
00051         _valid = false;
00052         return 0;
00053     }
00054 
00055     const usb_ep_entry_t &entry = _table->table[index_to_logical(index)];
00056     _cost += entry.base_cost + entry.byte_cost * size;
00057     _used |= 1 << index;
00058 
00059     return index_to_endpoint(index);
00060 
00061 }
00062 usb_ep_t EndpointResolver::endpoint_in(usb_ep_type_t type, uint32_t size)
00063 {
00064     return next_free_endpoint(true, type, size);
00065 }
00066 
00067 usb_ep_t EndpointResolver::endpoint_out(usb_ep_type_t type, uint32_t size)
00068 {
00069     return next_free_endpoint(false, type, size);
00070 }
00071 
00072 bool EndpointResolver::valid()
00073 {
00074     return _valid && (_cost <= _table->resources);
00075 }
00076 
00077 void EndpointResolver::reset()
00078 {
00079     _cost = 0;
00080     _used = 0;
00081     _valid = true;
00082 }
00083 
00084 usb_ep_t EndpointResolver::index_to_endpoint(int index)
00085 {
00086     return index_to_logical(index) | ((index & 1) ? 0x80 : 0);
00087 }
00088 
00089 int EndpointResolver::next_index(usb_ep_type_t type, bool in_not_out)
00090 {
00091     for (int logical = 0; logical < (int)(sizeof(_table->table) / sizeof(_table->table[0])); logical++) {
00092         uint32_t index = logical_to_index(logical, in_not_out);
00093         uint32_t other = logical_to_index(logical, !in_not_out);
00094         const usb_ep_entry_t &entry = _table->table[logical];
00095 
00096         usb_ep_attr_t dir = entry.attributes & USB_EP_ATTR_DIR_MASK;
00097         bool in_allowed = dir != USB_EP_ATTR_DIR_OUT;
00098         bool out_allowed = dir != USB_EP_ATTR_DIR_IN;
00099         bool shared = dir == USB_EP_ATTR_DIR_IN_OR_OUT;
00100 
00101         if (!(entry.attributes & (1 << type))) {
00102             // This type is not supported
00103             continue;
00104         }
00105 
00106         if (in_not_out && !in_allowed) {
00107             // In endpoint not supported
00108             continue;
00109         }
00110 
00111         if (!in_not_out && !out_allowed) {
00112             // Out endpoint not supported
00113             continue;
00114         }
00115 
00116         if (_used & (1 << index)) {
00117             // This endpoint is in use
00118             continue;
00119         }
00120 
00121         if (shared && (_used & (1 << other))) {
00122             // This endpoint can only be one direction at a time and is in
00123             // use by the other direction
00124             continue;
00125         }
00126 
00127         return index;
00128     }
00129 
00130     // Not found
00131     return -1;
00132 }