|
28 | 28 |
|
29 | 29 | #if (CFG_TUH_ENABLED && CFG_TUH_VENDOR) |
30 | 30 |
|
31 | | -//--------------------------------------------------------------------+ |
32 | | -// INCLUDE |
33 | | -//--------------------------------------------------------------------+ |
34 | | -#include "host/usbh.h" |
35 | | -#include "vendor_host.h" |
| 31 | + //--------------------------------------------------------------------+ |
| 32 | + // INCLUDE |
| 33 | + //--------------------------------------------------------------------+ |
| 34 | + #include "host/usbh.h" |
| 35 | + #include "host/usbh_pvt.h" |
| 36 | + #include "vendor_host.h" |
36 | 37 |
|
37 | 38 | //--------------------------------------------------------------------+ |
38 | 39 | // MACRO CONSTANT TYPEDEF |
|
41 | 42 | //--------------------------------------------------------------------+ |
42 | 43 | // INTERNAL OBJECT & FUNCTION DECLARATION |
43 | 44 | //--------------------------------------------------------------------+ |
| 45 | +typedef struct { |
| 46 | + uint8_t itf_num; |
| 47 | + uint8_t ep_in; |
| 48 | + uint8_t ep_out; |
| 49 | + bool setup; |
| 50 | +} custom_interface_info_t; |
| 51 | + |
44 | 52 | custom_interface_info_t custom_interface[CFG_TUH_DEVICE_MAX]; |
45 | 53 |
|
46 | | -static tusb_error_t cush_validate_paras(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length) |
47 | | -{ |
48 | | - if ( !tusbh_custom_is_mounted(dev_addr, vendor_id, product_id) ) |
49 | | - { |
50 | | - return TUSB_ERROR_DEVICE_NOT_READY; |
| 54 | + |
| 55 | +TU_ATTR_ALWAYS_INLINE static inline custom_interface_info_t *get_itf(uint8_t daddr) { |
| 56 | + return &custom_interface[daddr - 1]; |
| 57 | +} |
| 58 | + |
| 59 | +TU_ATTR_ALWAYS_INLINE static inline bool tusbh_custom_is_mounted(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id) { |
| 60 | + uint16_t vid, pid; |
| 61 | + TU_ASSERT(tuh_vid_pid_get(dev_addr, &vid, &pid)); |
| 62 | + |
| 63 | + custom_interface_info_t *p_cust = get_itf(dev_addr); |
| 64 | + return p_cust->setup && vid == vendor_id && pid == product_id; |
| 65 | +} |
| 66 | + |
| 67 | + |
| 68 | +static bool cush_validate_paras(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void *p_buffer, uint16_t length) { |
| 69 | + if (!tusbh_custom_is_mounted(dev_addr, vendor_id, product_id)) { |
| 70 | + TU_LOG1("Device not mounted or not setup!\n"); |
| 71 | + return false; |
51 | 72 | } |
52 | 73 |
|
53 | | - TU_ASSERT( p_buffer != NULL && length != 0, TUSB_ERROR_INVALID_PARA); |
| 74 | + TU_ASSERT(p_buffer != NULL && length != 0); |
54 | 75 |
|
55 | | - return TUSB_ERROR_NONE; |
| 76 | + return true; |
56 | 77 | } |
57 | 78 | //--------------------------------------------------------------------+ |
58 | 79 | // APPLICATION API (need to check parameters) |
59 | 80 | //--------------------------------------------------------------------+ |
60 | | -tusb_error_t tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length) |
61 | | -{ |
62 | | - TU_ASSERT_ERR( cush_validate_paras(dev_addr, vendor_id, product_id, p_buffer, length) ); |
| 81 | +bool tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, uint8_t *p_buffer, uint16_t length) { |
| 82 | + TU_ASSERT(cush_validate_paras(dev_addr, vendor_id, product_id, p_buffer, length)); |
63 | 83 |
|
64 | | - if ( !hcd_pipe_is_idle(custom_interface[dev_addr-1].pipe_in) ) |
65 | | - { |
66 | | - return TUSB_ERROR_INTERFACE_IS_BUSY; |
67 | | - } |
| 84 | + custom_interface_info_t *p_cust = get_itf(dev_addr); |
68 | 85 |
|
69 | | - (void) usbh_edpt_xfer( custom_interface[dev_addr-1].pipe_in, p_buffer, length); |
| 86 | + if (!usbh_edpt_claim(dev_addr, p_cust->ep_in)) { |
| 87 | + TU_LOG1("Couldn't claim endpoint :c\n"); |
| 88 | + return false; |
| 89 | + } |
70 | 90 |
|
71 | | - return TUSB_ERROR_NONE; |
| 91 | + if (!usbh_edpt_xfer(dev_addr, p_cust->ep_in, p_buffer, length)) { |
| 92 | + usbh_edpt_release(dev_addr, p_cust->ep_in); |
| 93 | + TU_LOG1("Couldn't read from endpoint :cc\n"); |
| 94 | + return false; |
| 95 | + } |
| 96 | + return true; |
72 | 97 | } |
73 | 98 |
|
74 | | -tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void const * p_data, uint16_t length) |
75 | | -{ |
76 | | - TU_ASSERT_ERR( cush_validate_paras(dev_addr, vendor_id, product_id, p_data, length) ); |
| 99 | +bool tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, uint8_t *p_data, uint16_t length) { |
| 100 | + TU_ASSERT(cush_validate_paras(dev_addr, vendor_id, product_id, p_data, length)); |
77 | 101 |
|
78 | | - if ( !hcd_pipe_is_idle(custom_interface[dev_addr-1].pipe_out) ) |
79 | | - { |
80 | | - return TUSB_ERROR_INTERFACE_IS_BUSY; |
81 | | - } |
| 102 | + custom_interface_info_t *p_cust = get_itf(dev_addr); |
82 | 103 |
|
83 | | - (void) usbh_edpt_xfer( custom_interface[dev_addr-1].pipe_out, p_data, length); |
| 104 | + if (!usbh_edpt_claim(dev_addr, p_cust->ep_out)) { |
| 105 | + TU_LOG1("Couldn't claim endpoint :c\n"); |
| 106 | + return false; |
| 107 | + } |
84 | 108 |
|
85 | | - return TUSB_ERROR_NONE; |
| 109 | + if (!usbh_edpt_xfer(dev_addr, p_cust->ep_out, p_data, length)) { |
| 110 | + usbh_edpt_release(dev_addr, p_cust->ep_out); |
| 111 | + TU_LOG1("Couldn't transfer to endpoint :cc\n"); |
| 112 | + return false; |
| 113 | + } |
| 114 | + return true; |
86 | 115 | } |
87 | 116 |
|
88 | 117 | //--------------------------------------------------------------------+ |
89 | 118 | // USBH-CLASS API |
90 | 119 | //--------------------------------------------------------------------+ |
91 | | -void cush_init(void) |
92 | | -{ |
| 120 | +bool cush_init(void) { |
93 | 121 | tu_memclr(&custom_interface, sizeof(custom_interface_info_t) * CFG_TUH_DEVICE_MAX); |
| 122 | + return true; |
94 | 123 | } |
95 | 124 |
|
96 | | -tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) |
97 | | -{ |
98 | | - // FIXME quick hack to test lpc1k custom class with 2 bulk endpoints |
99 | | - uint8_t const *p_desc = (uint8_t const *) p_interface_desc; |
100 | | - p_desc = tu_desc_next(p_desc); |
| 125 | +bool cush_deinit(void) { return true; } |
| 126 | + |
| 127 | +bool cush_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { |
| 128 | + uint8_t const *p_desc = tu_desc_next(itf_desc); |
| 129 | + uint8_t const* p_desc_end = ((uint8_t const*) itf_desc) + max_len; |
| 130 | + |
| 131 | + custom_interface_info_t *p_cust = get_itf(dev_addr); |
| 132 | + p_cust->setup = false; |
101 | 133 |
|
102 | 134 | //------------- Bulk Endpoints Descriptor -------------// |
103 | | - for(uint32_t i=0; i<2; i++) |
104 | | - { |
| 135 | + |
| 136 | + // We expect two endpoints for the heat it |
| 137 | + TU_LOG3("Num endpoints: %d\n", itf_desc->bNumEndpoints); |
| 138 | + TU_ASSERT(itf_desc->bNumEndpoints == 2); |
| 139 | + |
| 140 | + for (uint8_t i = 0; i < 2; i++) { |
| 141 | + TU_ASSERT(p_desc < p_desc_end); |
| 142 | + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)); |
105 | 143 | tusb_desc_endpoint_t const *p_endpoint = (tusb_desc_endpoint_t const *) p_desc; |
106 | | - TU_ASSERT(TUSB_DESC_ENDPOINT == p_endpoint->bDescriptorType, TUSB_ERROR_INVALID_PARA); |
107 | 144 |
|
108 | | - pipe_handle_t * p_pipe_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_IN_MASK ) ? |
109 | | - &custom_interface[dev_addr-1].pipe_in : &custom_interface[dev_addr-1].pipe_out; |
110 | | - *p_pipe_hdl = usbh_edpt_open(dev_addr, p_endpoint, TUSB_CLASS_VENDOR_SPECIFIC); |
111 | | - TU_ASSERT ( pipehandle_is_valid(*p_pipe_hdl), TUSB_ERROR_HCD_OPEN_PIPE_FAILED ); |
| 145 | + TU_LOG3("Open endpoint #%d\n", i); |
| 146 | + TU_ASSERT(tuh_edpt_open(dev_addr, p_endpoint)); |
| 147 | + |
| 148 | + if (TUSB_DIR_IN == tu_edpt_dir(p_endpoint->bEndpointAddress)) { |
| 149 | + p_cust->ep_in = p_endpoint->bEndpointAddress; |
| 150 | + } else { |
| 151 | + p_cust->ep_out = p_endpoint->bEndpointAddress; |
| 152 | + } |
112 | 153 |
|
113 | 154 | p_desc = tu_desc_next(p_desc); |
114 | 155 | } |
115 | 156 |
|
116 | | - (*p_length) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); |
117 | | - return TUSB_ERROR_NONE; |
118 | | -} |
| 157 | + p_cust->itf_num = itf_desc->bInterfaceNumber; |
| 158 | + p_cust->setup = true; |
119 | 159 |
|
120 | | -void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event) |
121 | | -{ |
| 160 | + TU_LOG3("Successfully setup!\n"); |
122 | 161 |
|
| 162 | + return true; |
123 | 163 | } |
124 | 164 |
|
125 | | -void cush_close(uint8_t dev_addr) |
126 | | -{ |
127 | | - tusb_error_t err1, err2; |
128 | | - custom_interface_info_t * p_interface = &custom_interface[dev_addr-1]; |
| 165 | +bool cush_set_config(uint8_t dev_addr, uint8_t itf_num) { |
| 166 | + custom_interface_info_t *p_hub = get_itf(dev_addr); |
| 167 | + TU_LOG3("Requesting to set interface %d and got %d\n", itf_num, p_hub->itf_num); |
| 168 | + TU_ASSERT(itf_num == p_hub->itf_num); |
| 169 | + |
| 170 | + // // Get Hub Descriptor |
| 171 | + // tusb_control_request_t const request = |
| 172 | + // { |
| 173 | + // .bmRequestType_bit = |
| 174 | + // { |
| 175 | + // .recipient = TUSB_REQ_RCPT_DEVICE, |
| 176 | + // .type = TUSB_REQ_TYPE_CLASS, |
| 177 | + // .direction = TUSB_DIR_IN |
| 178 | + // }, |
| 179 | + // .bRequest = HUB_REQUEST_GET_DESCRIPTOR, |
| 180 | + // .wValue = 0, |
| 181 | + // .wIndex = 0, |
| 182 | + // .wLength = sizeof(descriptor_hub_desc_t) |
| 183 | + // }; |
| 184 | + |
| 185 | + // tuh_xfer_t xfer = |
| 186 | + // { |
| 187 | + // .daddr = dev_addr, |
| 188 | + // .ep_addr = 0, |
| 189 | + // .setup = &request, |
| 190 | + // .buffer = _hub_buffer, |
| 191 | + // .complete_cb = config_set_port_power, |
| 192 | + // .user_data = 0 |
| 193 | + // }; |
| 194 | + |
| 195 | + // TU_ASSERT( tuh_control_xfer(&xfer) ); |
| 196 | + |
| 197 | + return true; |
| 198 | +} |
129 | 199 |
|
130 | | - // TODO re-consider to check pipe valid before calling pipe_close |
131 | | - if( pipehandle_is_valid( p_interface->pipe_in ) ) |
132 | | - { |
133 | | - err1 = hcd_pipe_close( p_interface->pipe_in ); |
134 | | - } |
135 | 200 |
|
136 | | - if ( pipehandle_is_valid( p_interface->pipe_out ) ) |
137 | | - { |
138 | | - err2 = hcd_pipe_close( p_interface->pipe_out ); |
139 | | - } |
| 201 | +TU_ATTR_WEAK bool cush_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { |
| 202 | + // TODO handle stall response, retry failed transfer ... |
| 203 | + TU_ASSERT(result == XFER_RESULT_SUCCESS); |
| 204 | + return true; |
| 205 | +} |
140 | 206 |
|
141 | | - tu_memclr(p_interface, sizeof(custom_interface_info_t)); |
| 207 | +void cush_close(uint8_t dev_addr) { |
| 208 | + TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); |
| 209 | + custom_interface_info_t *p_cust = get_itf(dev_addr); |
142 | 210 |
|
143 | | - TU_ASSERT(err1 == TUSB_ERROR_NONE && err2 == TUSB_ERROR_NONE, (void) 0 ); |
| 211 | + tu_memclr(p_cust, sizeof(custom_interface_info_t)); |
144 | 212 | } |
145 | 213 |
|
146 | 214 | #endif |
0 commit comments