Skip to content

Commit cd01134

Browse files
committed
implement vendor usb host interfaces
1 parent 86ad6e5 commit cd01134

3 files changed

Lines changed: 145 additions & 85 deletions

File tree

src/class/vendor/vendor_host.c

Lines changed: 132 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,12 @@
2828

2929
#if (CFG_TUH_ENABLED && CFG_TUH_VENDOR)
3030

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"
3637

3738
//--------------------------------------------------------------------+
3839
// MACRO CONSTANT TYPEDEF
@@ -41,106 +42,173 @@
4142
//--------------------------------------------------------------------+
4243
// INTERNAL OBJECT & FUNCTION DECLARATION
4344
//--------------------------------------------------------------------+
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+
4452
custom_interface_info_t custom_interface[CFG_TUH_DEVICE_MAX];
4553

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;
5172
}
5273

53-
TU_ASSERT( p_buffer != NULL && length != 0, TUSB_ERROR_INVALID_PARA);
74+
TU_ASSERT(p_buffer != NULL && length != 0);
5475

55-
return TUSB_ERROR_NONE;
76+
return true;
5677
}
5778
//--------------------------------------------------------------------+
5879
// APPLICATION API (need to check parameters)
5980
//--------------------------------------------------------------------+
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));
6383

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);
6885

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+
}
7090

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;
7297
}
7398

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));
77101

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);
82103

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+
}
84108

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;
86115
}
87116

88117
//--------------------------------------------------------------------+
89118
// USBH-CLASS API
90119
//--------------------------------------------------------------------+
91-
void cush_init(void)
92-
{
120+
bool cush_init(void) {
93121
tu_memclr(&custom_interface, sizeof(custom_interface_info_t) * CFG_TUH_DEVICE_MAX);
122+
return true;
94123
}
95124

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;
101133

102134
//------------- 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));
105143
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);
107144

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+
}
112153

113154
p_desc = tu_desc_next(p_desc);
114155
}
115156

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;
119159

120-
void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event)
121-
{
160+
TU_LOG3("Successfully setup!\n");
122161

162+
return true;
123163
}
124164

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+
}
129199

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-
}
135200

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+
}
140206

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);
142210

143-
TU_ASSERT(err1 == TUSB_ERROR_NONE && err2 == TUSB_ERROR_NONE, (void) 0 );
211+
tu_memclr(p_cust, sizeof(custom_interface_info_t));
144212
}
145213

146214
#endif

src/class/vendor/vendor_host.h

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,31 +33,20 @@
3333
extern "C" {
3434
#endif
3535

36-
typedef struct {
37-
pipe_handle_t pipe_in;
38-
pipe_handle_t pipe_out;
39-
}custom_interface_info_t;
40-
4136
//--------------------------------------------------------------------+
4237
// USBH-CLASS DRIVER API
4338
//--------------------------------------------------------------------+
44-
static inline bool tusbh_custom_is_mounted(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id)
45-
{
46-
(void) vendor_id; // TODO check this later
47-
(void) product_id;
48-
// return (tusbh_device_get_mounted_class_flag(dev_addr) & TU_BIT(TUSB_CLASS_MAPPED_INDEX_END-1) ) != 0;
49-
return false;
50-
}
51-
52-
bool tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length);
53-
bool tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void const * p_data, uint16_t length);
39+
bool tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, uint8_t * p_buffer, uint16_t length);
40+
bool tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, uint8_t * p_data, uint16_t length);
5441

5542
//--------------------------------------------------------------------+
5643
// Internal Class Driver API
5744
//--------------------------------------------------------------------+
58-
void cush_init(void);
59-
bool cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length);
60-
void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event);
45+
bool cush_init(void);
46+
bool cush_deinit(void);
47+
bool cush_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len);
48+
bool cush_set_config(uint8_t dev_addr, uint8_t itf_num);
49+
bool cush_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
6150
void cush_close(uint8_t dev_addr);
6251

6352
#ifdef __cplusplus

src/host/usbh.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ typedef struct {
127127
// uint8_t interface_count; // bNumInterfaces alias
128128

129129
// Endpoint & Interface
130-
uint8_t itf2drv[CFG_TUH_INTERFACE_MAX]; // map interface number to driver (0xff is invalid)
130+
uint8_t itf2drv[CFG_TUH_INTERFACE_MAX ? CFG_TUH_INTERFACE_MAX : 1]; // map interface number to driver (0xff is invalid)
131131
uint8_t ep2drv[CFG_TUH_ENDPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ), can use only 4-bit each
132132

133133
tu_edpt_state_t ep_status[CFG_TUH_ENDPOINT_MAX][2];
@@ -205,9 +205,9 @@ static usbh_class_driver_t const usbh_class_drivers[] = {
205205
.name = DRIVER_NAME("VENDOR"),
206206
.init = cush_init,
207207
.deinit = cush_deinit,
208-
.open = cush_open,
208+
.open = cush_open_subtask,
209209
.set_config = cush_set_config,
210-
.xfer_cb = cush_isr,
210+
.xfer_cb = cush_xfer_cb,
211211
.close = cush_close
212212
}
213213
#endif
@@ -1754,12 +1754,15 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) {
17541754
}
17551755

17561756
// all interface are configured
1757+
1758+
TU_LOG_USBH("Itf_num=%u INTERFACE_MAX=%u\r\n", itf_num, CFG_TUH_INTERFACE_MAX);
17571759
if (itf_num == CFG_TUH_INTERFACE_MAX) {
17581760
enum_full_complete();
17591761

17601762
if (is_hub_addr(dev_addr)) {
17611763
TU_LOG_USBH("HUB address = %u is mounted\r\n", dev_addr);
17621764
}else {
1765+
TU_LOG_USBH("INVODE MOUNT CALLBACK\r\n");
17631766
// Invoke callback if available
17641767
if (tuh_mount_cb) tuh_mount_cb(dev_addr);
17651768
}

0 commit comments

Comments
 (0)