source: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/HUB/tusbh_hub.c@ 453

Last change on this file since 453 was 453, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 13.0 KB
Line 
1/*
2 * TOPPERS BASE PLATFORM MIDDLEWARE
3 *
4 * Copyright (C) 2017-2017 by TOPPERS PROJECT
5 * Educational Working Group.
6 *
7 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
8 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
9 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
10 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
11 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
12 * スコード中に含まれていること.
13 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
14 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
15 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
16 * の無保証規定を掲載すること.
17 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
18 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
19 * と.
20 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
21 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
22 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
23 * 報告すること.
24 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
25 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
26 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
27 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
28 * 免責すること.
29 *
30 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
31 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
32 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
33 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
34 * の責任を負わない.
35 *
36 * @(#) $Id$
37 */
38/*
39 * USB Host Middleware HUB CLASS部
40 */
41
42#include "tusbh_hub.h"
43
44#define CLASS_GETDESC_TYPE (USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS)
45#define PORT_POWER_FEATURE(d, p) tusbhControlRequest((d), NULL, PORT_SETFEATURE_TYPE, SET_FEATURE, PORT_POWERFEATURE, (p), 0)
46#define PORT_RESET_FEATURE(d, p) tusbhControlRequest((d), NULL, PORT_SETFEATURE_TYPE, SET_FEATURE, PORT_RESETFEATURE, (p), 0)
47#define PORT_CLEAR_FEATURE(d, f, p) tusbhControlRequest((d), NULL, PORT_CLEARFEATURE_TYPE, CLEAR_FEATURE, (f), (p), 0)
48#define PORT_GET_STATUS(d, b, p) tusbhControlRequest((d), (b), PORT_GETSTATUS_TYPE, GET_STATUS, 0, (p), 4)
49
50#define GET_PORT(i) (i+1)
51
52
53static TUSBH_ERCODE tusbhHUBInit(TUSBH_Device_t *pdevice);
54static TUSBH_ERCODE tusbhHUBDeInit(TUSBH_Device_t *pdevice);
55static TUSBH_ERCODE tusbhHUBProcess(TUSBH_Device_t *pdevice, uint8_t *mes);
56
57static TUSBH_Class_t HUB_Class = {
58 NULL,
59 "HUB",
60 HUB_CLASS,
61 tusbhHUBInit,
62 tusbhHUBDeInit,
63 tusbhHUBProcess,
64 NULL
65};
66
67/*
68 * HUBクラスセットアップ関数
69 */
70void tusbhLinkHUB(TUSBH_Handle_t *phost)
71{
72 tusbhLinkClass(phost, &HUB_Class);
73}
74
75
76/*
77 * HUBクラス初期設定
78 * parameter1 pdevice: デバイスハンドラ
79 * return TUSBH_ERCODE
80 */
81static TUSBH_ERCODE
82tusbhHUBInit(TUSBH_Device_t *pdevice)
83{
84 uint8_t interface = 0;
85 HUB_Handle_t *hhub;
86 TUSBH_Handle_t *phost = pdevice->pHost;
87 uint8_t max_ep, i;
88
89 interface = tusbhFindInterface(pdevice, pdevice->pClass->classCode, 0, 0);
90
91 if(interface == NO_INTERFACE){
92 syslog_1(LOG_ERROR, "[HUB] Cannot Find the interface for %s class.", pdevice->pClass->Name);
93 return TUSBH_E_ERR;
94 }
95
96 tusbhSelectInterface(pdevice, interface);
97 hhub = (HUB_Handle_t *)tusbmalloc(sizeof(HUB_Handle_t));
98 pdevice->pData = hhub;
99 memset(hhub, 0, sizeof(HUB_Handle_t));
100 hhub->hubid = ++phost->numHub;
101 pdevice->hubid = hhub->hubid;
102 hhub->state = THUB_IDLE;
103 hhub->cstate = THUB_CONNCET_IDEL;
104 hhub->ep_addr = pdevice->EpDesc[pdevice->sel_interface][0].bEndpointAddress;
105 hhub->length = pdevice->EpDesc[pdevice->sel_interface][0].wMaxPacketSize;
106 hhub->poll = pdevice->EpDesc[pdevice->sel_interface][0].bInterval;
107
108 max_ep = pdevice->ItfDesc[pdevice->sel_interface].bNumEndpoints;
109 if(max_ep == 0 || (pdevice->EpDesc[pdevice->sel_interface][0].bEndpointAddress & 0x80) == 0)
110 return TUSBH_E_ERR;
111
112
113 syslog_4(LOG_NOTICE, "## max_ep(%d) length(%d) poll(%d) b(%d) ##", max_ep, hhub->length, hhub->poll, offsetof(HUB_Handle_t, buffer));
114 hhub->InPipe = tusbhAllocPipe(phost, hhub->ep_addr);
115
116 /*
117 * IN ENDPOINT OPEN
118 */
119 tusbhOpenPipe(pdevice, hhub->InPipe, hhub->ep_addr, USB_EP_TYPE_INTR, hhub->length);
120 tusbhHDSetToggle(phost, hhub->InPipe, 0);
121
122 if(tusbhGetDescriptor(pdevice, CLASS_GETDESC_TYPE, (0x29 << 8), hhub->buffer, sizeof(HubDescriptor)) != TUSBH_E_OK)
123 return TUSBH_E_ERR;
124 hhub->numport = hhub->buffer[2];
125 hhub->characteristics = hhub->buffer[3];
126 hhub->starttime = hhub->buffer[5] * 2;
127 syslog_1(LOG_NOTICE, "## hhub->numport(%d) ##", hhub->numport);
128
129 for(i = 0 ; i < hhub->numport ; i++){
130 PORT_POWER_FEATURE(pdevice, GET_PORT(i));
131 }
132
133 /* タイマースタート */
134 hhub->timer = 0;
135 pdevice->timeid = pdevice->timecount = hhub->poll;
136 return TUSBH_E_OK;
137}
138
139/*
140 * HUBクラス終了設定
141 * parameter1 pdevice: デバイスハンドラ
142 * return TUSBH_ERCODE
143 */
144static TUSBH_ERCODE
145tusbhHUBDeInit(TUSBH_Device_t *pdevice)
146{
147 HUB_Handle_t *hhub = (HUB_Handle_t *)pdevice->pData;
148 TUSBH_Handle_t *phost = pdevice->pHost;
149
150 if(hhub->InPipe != 0){
151 tusbhClosePipe(pdevice, hhub->InPipe);
152 tusbFreePipe(phost, hhub->InPipe);
153 hhub->InPipe = 0;
154 }
155 if(phost->numHub > 0)
156 phost->numHub--;
157
158 if(pdevice->pData != NULL){
159 tusbfree(pdevice->pData);
160 pdevice->pData = NULL;
161 }
162 return TUSBH_E_OK;
163}
164
165/*
166 * HUBクラスプロセス実行
167 * parameter1 pdevice: デバイスハンドラ
168 * parameter2 mes: 通信メッセージへのポインタ
169 * return TUSBH_ERCODE
170 */
171static TUSBH_ERCODE
172tusbhHUBProcess(TUSBH_Device_t *pdevice, uint8_t *mes)
173{
174 HUB_Handle_t *hhub;
175 TUSBH_Handle_t *phost = pdevice->pHost;
176 TUSBH_Device_t *pdevicep;
177 TUSBH_ERCODE status = TUSBH_E_OK;
178 TUSBH_URBState_t URB_Status = mes[3];
179 uint32_t pstatus = 0;
180 uint32_t i;
181
182 hhub = (HUB_Handle_t *)pdevice->pData;
183 if(mes[0] == TUSBH_TIME_EVENT)
184 hhub->timer += mes[3];
185 else if(mes[0] == TUSBH_RESET_EVENT)
186 hhub->reset_portid = mes[3];
187 switch (hhub->state){
188 case THUB_IDLE:
189 if(phost->usrcallback != NULL)
190 phost->usrcallback(phost, pdevice, HOST_USER_CLASS_ACTIVE);
191 hhub->state = THUB_SYNC;
192 case THUB_SYNC:
193 if(hhub->timer < hhub->starttime){
194 pdevice->timecount = hhub->poll;
195 break;
196 }
197 hhub->portno = 0;
198 hhub->cstate = THUB_CONNCET_IDEL;
199 if(hhub->reset_portid > 0){
200 PORT_RESET_FEATURE(pdevice, hhub->reset_portid);
201 hhub->state = THUB_PORT_RESET_WAIT;
202 hhub->reset_portid = 0;
203 }
204 case THUB_GET_DATA:
205 tusbhInterruptRead(pdevice, hhub->buffer, hhub->length, hhub->InPipe);
206 hhub->state = THUB_POLL;
207 break;
208 case THUB_POLL:
209 if(mes[0] != TUSBH_URB_EVENT)
210 break;
211 if(URB_Status == TUSBH_URB_DONE){
212 PORT_GET_STATUS(pdevice, hhub->buffer, GET_PORT(hhub->portno));
213 hhub->state = THUB_GET_STATUS_WAIT;
214 }
215 else if(URB_Status == TUSBH_URB_STALL){ /* IN Endpoint Stalled */
216 hhub->state = THUB_PORT_ERROR;
217 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
218 }
219 else{
220 hhub->state = THUB_GET_DATA;
221 pdevice->timecount = hhub->poll;
222 }
223 break;
224 case THUB_GET_STATUS_WAIT:
225 if((status = tusbhControlWait(pdevice, mes)) == TUSBH_E_OK){
226 uint8_t speed;
227 pstatus = hhub->buffer[0];
228 pstatus |= hhub->buffer[1] << 8;
229 pstatus |= hhub->buffer[2] << 16;
230 pstatus |= hhub->buffer[3] << 24;
231#if 1 /* ROI DEBUG */
232 if((pstatus & 0xffff0000) != 0)
233 syslog_2(LOG_NOTICE, "## PSTATUS port(%d) status[%08x] ##", hhub->portno, pstatus);
234#endif /* ROI DEBUG */
235
236 if((pstatus & PORT_CHANGE_CONNECTION) != 0){
237 if((pstatus & PORT_STATUS_CONNECTION) != 0)
238 hhub->cstate = THUB_CONNECT_RESET;
239 else
240 tusbSendData(phost->connect_event, TUSBH_DISCONNECT_EVENT, hhub->hubid, GET_PORT(hhub->portno), 0);
241 PORT_CLEAR_FEATURE(pdevice, PORT_CLEAR_CONNECTION_FEATURE, GET_PORT(hhub->portno));
242 hhub->state = THUB_CLEAR_FEATURE_WAIT;
243 }
244 else if((pstatus & PORT_CHANGE_RESET) != 0){
245 PORT_CLEAR_FEATURE(pdevice, PORT_CLEAR_RESET_FEATURE, GET_PORT(hhub->portno));
246 hhub->state = THUB_CLEAR_FEATURE_WAIT;
247 if(hhub->cstate == THUB_CONNECT_RESET){
248 if((pstatus & (PORT_STATUS_CONNECTION | PORT_STATUS_ENABLE)) == (PORT_STATUS_CONNECTION | PORT_STATUS_ENABLE)){
249 hhub->cstate = THUB_CONNECT_ENABLE;
250 if((pstatus & PORT_STATUS_LOW_SPEED) != 0)
251 speed = USB_DEVICE_SPEED_LOW;
252 else
253 speed = USB_DEVICE_SPEED_FULL;
254 tusbSendData(phost->connect_event, TUSBH_CONNECT_EVENT, hhub->hubid, GET_PORT(hhub->portno), speed);
255 }
256 }
257 }
258 else if((pstatus & PORT_CHANGE_ENABLE) != 0){
259 PORT_CLEAR_FEATURE(pdevice, PORT_CLEAR_ENABLE_FEATURE, GET_PORT(hhub->portno));
260 hhub->state = THUB_CLEAR_FEATURE_WAIT;
261 if(hhub->cstate == THUB_CONNECT_RESET){
262 if((pstatus & (PORT_STATUS_CONNECTION | PORT_STATUS_ENABLE)) == (PORT_STATUS_CONNECTION | PORT_STATUS_ENABLE)){
263 hhub->cstate = THUB_CONNECT_ENABLE;
264 if((pstatus & PORT_STATUS_LOW_SPEED) != 0)
265 speed = USB_DEVICE_SPEED_LOW;
266 else
267 speed = USB_DEVICE_SPEED_FULL;
268 tusbSendData(phost->connect_event, TUSBH_CONNECT_EVENT, hhub->hubid, GET_PORT(hhub->portno), speed);
269 }
270 }
271 }
272 else if((pstatus & PORT_CHANGE_OVER_CURRENT) != 0){
273 tusbSendData(phost->connect_event, TUSBH_DISCONNECT_EVENT, hhub->hubid, GET_PORT(hhub->portno), 0);
274 PORT_CLEAR_FEATURE(pdevice, PORT_OVER_CURRENT_FEATURE, GET_PORT(hhub->portno));
275 hhub->state = THUB_CLEAR_FEATURE_WAIT;
276 }
277// else if(hhub->connect != 0){
278 else if(hhub->cstate != THUB_CONNCET_IDEL){
279 hhub->state = THUB_GET_DATA;
280 pdevice->timecount = hhub->poll;
281 }
282 else if(++hhub->portno < hhub->numport){
283 PORT_GET_STATUS(pdevice, hhub->buffer, GET_PORT(hhub->portno));
284 hhub->state = THUB_GET_STATUS_WAIT;
285 }
286 else{
287 hhub->state = THUB_SYNC;
288 pdevice->timecount = hhub->poll;
289 }
290 }
291 else if(status != TUSBH_E_BUSY && status != TUSBH_E_BUSY_URB){
292 hhub->state = THUB_PORT_ERROR;
293 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
294 }
295 break;
296 case THUB_CLEAR_FEATURE_WAIT:
297 if((status = tusbhControlWait(pdevice, mes)) == TUSBH_E_OK){
298 if(hhub->cstate == THUB_CONNECT_RESET){
299 PORT_RESET_FEATURE(pdevice, GET_PORT(hhub->portno));
300 hhub->state = THUB_PORT_RESET_WAIT;
301 }
302 else if(hhub->cstate == THUB_CONNECT_ENABLE){
303 hhub->state = THUB_CONNECT_WAIT;
304 pdevice->timecount = 50;
305 }
306 else if(++hhub->portno < hhub->numport){
307 PORT_GET_STATUS(pdevice, hhub->buffer, GET_PORT(hhub->portno));
308 hhub->state = THUB_GET_STATUS_WAIT;
309 }
310 else{
311 hhub->state = THUB_SYNC;
312 pdevice->timecount = hhub->poll;
313 }
314 }
315 else if(status != TUSBH_E_BUSY && status != TUSBH_E_BUSY_URB){
316 hhub->state = THUB_PORT_ERROR;
317 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
318 }
319 break;
320 case THUB_PORT_RESET_WAIT:
321 if((status = tusbhControlWait(pdevice, mes)) == TUSBH_E_OK){
322 hhub->state = THUB_GET_DATA;
323 pdevice->timecount = hhub->poll;
324 }
325 else if(status != TUSBH_E_BUSY && status != TUSBH_E_BUSY_URB){
326 hhub->state = THUB_PORT_ERROR;
327 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
328 }
329 break;
330 case THUB_CONNECT_WAIT:
331 pdevice->timecount = 200;
332 for(i = 0, pdevicep = phost->pDevice ; i < phost->numDevice && pdevicep != NULL ; i++){
333 if(pdevicep->hub == hhub->hubid && pdevicep->port == GET_PORT(hhub->portno)){
334 if(pdevicep->dstate >= DEVICE_CLASS){
335 if(pdevicep->pClass != NULL)
336 syslog_2(LOG_NOTICE, "[HUB] connected idx(%d) class[%s] !", pdevicep->idx, pdevicep->pClass->Name);
337 hhub->cstate = THUB_CONNCET_IDEL;
338 if(++hhub->portno < hhub->numport){
339 PORT_GET_STATUS(pdevice, hhub->buffer, GET_PORT(hhub->portno));
340 hhub->state = THUB_GET_STATUS_WAIT;
341 }
342 else{
343 hhub->state = THUB_SYNC;
344 pdevice->timecount = hhub->poll;
345 }
346 }
347 break;
348 }
349 pdevicep = pdevicep->pNext;
350 }
351 break;
352 case THUB_PORT_ERROR:
353 tusbhClearFeature(pdevice, hhub->ep_addr);
354 hhub->state = THUB_PORT_ERROR_WAIT;
355 break;
356 case THUB_PORT_ERROR_WAIT:
357 if(tusbhControlWait(pdevice, mes) == TUSBH_E_OK){
358 hhub->state = THUB_SYNC;
359 pdevice->timecount = hhub->poll;
360 }
361 else if(status == TUSBH_E_BUSY_URB)
362 status = TUSBH_E_BUSY;
363 break;
364
365 default:
366 break;
367 }
368 return status;
369}
370
Note: See TracBrowser for help on using the repository browser.