source: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/tusbh_request.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: 15.9 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 通信リクエスト部
40 */
41
42#include "tusbh_base.h"
43
44
45/*
46 * BULK通信:WRITE
47 * parameter1 pdevice: デバイスハンドラ
48 * parameter2 buff: データ領域
49 * parameter3 length: データ長
50 * parameter4 pipe_num: PIPE番号
51 * return TUSBH_ERCOCE
52 */
53TUSBH_ERCODE
54tusbhBulkWrite(TUSBH_Device_t *pdevice, uint8_t *buff, uint16_t length, uint8_t pipe_num)
55{
56 return tusbhSubmitURB(pdevice, pipe_num, SUBMIT_WRITE, USB_EP_TYPE_BULK, buff, length);
57}
58
59/*
60 * BULK通信:READ
61 * parameter1 pdevice: デバイスハンドラ
62 * parameter2 buff: データ領域
63 * parameter3 length: データ長
64 * parameter4 pipe_num: PIPE番号
65 * return TUSBH_ERCOCE
66 */
67TUSBH_ERCODE
68tusbhBulkRead(TUSBH_Device_t *pdevice, uint8_t *buff, uint16_t length, uint8_t pipe_num)
69{
70 return tusbhSubmitURB(pdevice, pipe_num, SUBMIT_READ, USB_EP_TYPE_BULK, buff, length);
71}
72
73/*
74 * INTERRUPT通信:WRITE
75 * parameter1 pdevice: デバイスハンドラ
76 * parameter2 buff: データ領域
77 * parameter3 length: データ長
78 * parameter4 pipe_num: PIPE番号
79 * return TUSBH_ERCOCE
80 */
81TUSBH_ERCODE
82tusbhInterruptWrite(TUSBH_Device_t *pdevice, uint8_t *buff, uint8_t length, uint8_t pipe_num)
83{
84 return tusbhSubmitURB(pdevice, pipe_num, SUBMIT_WRITE, USB_EP_TYPE_INTR, buff, length);
85}
86
87/*
88 * INTERRUPT通信:READ
89 * parameter1 pdevice: デバイスハンドラ
90 * parameter2 buff: データ領域
91 * parameter3 length: データ長
92 * parameter4 pipe_num: PIPE番号
93 * return TUSBH_ERCOCE
94 */
95TUSBH_ERCODE
96tusbhInterruptRead(TUSBH_Device_t *pdevice, uint8_t *buff, uint8_t length, uint8_t pipe_num)
97{
98 return tusbhSubmitURB(pdevice, pipe_num, SUBMIT_READ, USB_EP_TYPE_INTR, buff, length);
99}
100
101/*
102 * ISOC通信:WRITE
103 * parameter1 pdevice: デバイスハンドラ
104 * parameter2 buff: データ領域
105 * parameter3 length: データ長
106 * parameter4 pipe_num: PIPE番号
107 * return TUSBH_ERCOCE
108 */
109TUSBH_ERCODE
110tusbhIsocWrite(TUSBH_Device_t *pdevice, uint8_t *buff, uint32_t length, uint8_t pipe_num)
111{
112 return tusbhSubmitURB(pdevice, pipe_num, SUBMIT_WRITE, USB_EP_TYPE_ISOC, buff, length);
113}
114
115/**
116 * @brief USBH_IsocReceiveData
117 * Receives the Device Response to the Isochronous IN token
118 * @param phost: Host Handle
119 * @param buff: Buffer pointer in which the response needs to be copied
120 * @param length: Length of the data to be received
121 * @param pipe_num: Pipe Number
122 * @retval USBH Status.
123 */
124TUSBH_ERCODE
125tusbhIsocRead(TUSBH_Device_t *pdevice, uint8_t *buff, uint32_t length, uint8_t pipe_num)
126{
127 return tusbhSubmitURB(pdevice, pipe_num, SUBMIT_READ, USB_EP_TYPE_ISOC, buff, length);
128}
129
130
131/*
132 * コントロール通信:SETUP送信
133 * parameter1 pdevice: デバイスハンドラ
134 * parameter2 buff: セットアップデータ領域
135 * parameter3 pipe_num: PIPE番号
136 * return TUSBH_ERCOCE
137 */
138TUSBH_ERCODE
139tusbhControlSendSetup(TUSBH_Device_t *pdevice, uint8_t *buff, uint8_t pipe_num)
140{
141 return tusbhSubmitURB(pdevice, pipe_num, SUBMIT_SETUP, USB_EP_TYPE_CTRL, buff, SETUP_PKT_LENGTH);
142}
143
144/*
145 * コントロール通信:データ送信
146 * parameter1 pdevice: デバイスハンドラ
147 * parameter2 buff: データ領域
148 * parameter3 length: データ長
149 * parameter4 pipe_num: パイプ番号
150 * return TUSBH_ERCOCE
151 */
152TUSBH_ERCODE
153tusbhControlSendData(TUSBH_Device_t *pdevice, uint8_t *buff, uint16_t length, uint8_t pipe_num)
154{
155 return tusbhSubmitURB(pdevice, pipe_num, SUBMIT_WRITE, USB_EP_TYPE_CTRL, buff, length);
156}
157
158/*
159 * コントロール通信:データ受信
160 * parameter1 pdevice: デバイスハンドラ
161 * parameter2 buff: データ領域
162 * parameter3 length: データ長
163 * parameter4 pipe_num: パイプ番号
164 * return TUSBH_ERCOCE
165 */
166TUSBH_ERCODE
167tusbhControlReceiveData(TUSBH_Device_t *pdevice, uint8_t* buff, uint16_t length, uint8_t pipe_num)
168{
169 return tusbhSubmitURB(pdevice, pipe_num, SUBMIT_READ, USB_EP_TYPE_CTRL, buff, length);
170}
171
172/*
173 * コントロール通信:DESCRIPTOR取得
174 * parameter1 pdevice: デバイスハンドラ
175 * parameter2 req_type: DESCRIPTORタイプ
176 * parameter3 value: DESCRIPTOR要求値
177 * parameter4 buff: DESCRIPTO格納領域
178 * parameter5 length: DESCRIPTOR長
179 * return TUSBH_ERCOCE
180 */
181TUSBH_ERCODE
182tusbhGetDescriptor(TUSBH_Device_t *pdevice, uint8_t req_type, uint16_t value, uint8_t* buff, uint16_t length)
183{
184 uint16_t index;
185
186 if((value & 0xff00) == ((STRING_DESCRIPTOR << 8) & 0xFF00)){
187 index = 0x0409;
188 }
189 else
190 index = 0;
191 return tusbhControlRequest(pdevice, buff, (USB_DEVICE_TO_HOST | req_type), GET_DESCRIPTOR, value, index, length );
192}
193
194/*
195 * コントロール通信:SET INTERFACEの送信
196 * parameter1 pdevice: デバイスハンドラ
197 * parameter2 ep_num: エンドポイント番号
198 * parameter3 interface: インタフェース値
199 * return TUSBH_ERCOCE
200 */
201TUSBH_ERCODE
202tusbhSetInterface(TUSBH_Device_t *pdevice, uint8_t ep_num, uint8_t interface)
203{
204 return tusbhControlRequest(pdevice, 0, SET_INTERFACE_TYPE, SET_INTERFACE, interface, ep_num, 0);
205}
206
207/*
208 * コントロール通信:CLEAR FEATUREの送信
209 * parameter1 pdevice: デバイスハンドラ
210 * parameter2 ep_num: エンドポイント番号
211 * return TUSBH_ERCOCE
212 */
213TUSBH_ERCODE
214tusbhClearFeature(TUSBH_Device_t *pdevice, uint8_t ep_num)
215{
216 return tusbhControlRequest(pdevice, 0, CLEAR_FEATURE_TYPE, CLEAR_FEATURE, FEATURE_SELECTOR_ENDPOINT, ep_num, 0 );
217}
218
219
220/*
221 * コントロール通信の要求
222 * parameter1 pdevice: デバイスハンドラ
223 * parameter2 buff: 通信バッファ
224 * parameter3 type: bmRequestType
225 * parameter4 request: bRequest
226 * parameter5 value: wValue
227 * parameter6 index: wIndex
228 * parameter7 length: wLength
229 * return TUSBH_ERCOCE
230 */
231TUSBH_ERCODE
232tusbhControlRequest(TUSBH_Device_t *pdevice, uint8_t *buff, uint8_t type, uint8_t request, uint16_t value, uint16_t index, uint16_t length)
233{
234 TUSBH_Handle_t *phost = pdevice->pHost;
235 TUSBH_ERCODE ercd = TUSBH_E_BUSY;
236 uint8_t mes[4];
237
238 pdevice->cstate = CONTROL_SETUP;
239 pdevice->setupPacket[0] = type;
240 pdevice->setupPacket[1] = request;
241 pdevice->setupPacket[2] = (uint8_t)value;
242 pdevice->setupPacket[3] = (uint8_t)(value >> 8);
243 pdevice->setupPacket[4] = (uint8_t)index;
244 pdevice->setupPacket[5] = (uint8_t)(index >> 8);
245 pdevice->setupPacket[6] = (uint8_t)length;
246 pdevice->setupPacket[7] = (uint8_t)(length >> 8);
247 pdevice->cbuff = buff;
248 mes[0] = TUSBH_PORT_EVENT;
249
250 do{
251 ercd = tusbhControlWait(pdevice, mes);
252 if(pdevice->dstate == DEVICE_CLASS)
253 return ercd;
254 while(ercd == TUSBH_E_BUSY_URB){
255 if(tusbRecvData(phost->process_event, mes, 4000) != E_OK){
256 syslog_1(LOG_ERROR, "tusbhControlRequest urb timeout state(%d) !", pdevice->cstate);
257 ercd = TUSBH_E_TMOUT;
258 break;
259 }
260 else if(mes[0] == TUSBH_URB_EVENT && mes[1] == pdevice->idx){
261 ercd = TUSBH_E_BUSY;
262 }
263 else if(mes[1] != pdevice->idx){
264 TUSBH_Device_t *pdevice2 = phost->pDevice;
265 uint8_t i;
266 for(i = 0 ; i < mes[1] ; i++)
267 pdevice2 = pdevice2->pNext;
268 if(pdevice2 != NULL && pdevice2->pClass != NULL && pdevice2->dstate == DEVICE_CLASS)
269 pdevice2->pClass->Process(pdevice2, mes);
270 else{
271#if 1 /* ROI DEBUG */
272 syslog_4(LOG_ERROR, "### tusbhControlRequest Can't EXEC [%02x][%02x][%02x][%02x] ###", mes[0], mes[1], mes[2], mes[3]);
273#endif /* ROI DEBUG */
274 tusbDelay(10);
275 tusbSendData(phost->process_event, mes[0], mes[1], mes[2], mes[3]);
276 }
277 }
278 }
279 }while(ercd == TUSBH_E_BUSY);
280 return ercd;
281}
282
283/*
284 * コントロール通信の待ち
285 * parameter1 pdevice: デバイスハンドラ
286 * parameter2 mes: メッセージへのポインタ
287 * return TUSBH_ERCOCE
288 */
289TUSBH_ERCODE
290tusbhControlWait(TUSBH_Device_t *pdevice, uint8_t *mes)
291{
292 TUSBH_Handle_t *phost = pdevice->pHost;
293 TUSBH_ERCODE ercd = TUSBH_E_BUSY;
294 TUSBH_URBState_t URB_Status = mes[3];
295 uint8_t type = pdevice->setupPacket[0];
296 uint16_t length = (pdevice->setupPacket[7] << 8) | (pdevice->setupPacket[6] & 0xFF);
297
298 switch(pdevice->cstate){
299 case CONTROL_SETUP: /* PACKETセットアップ */
300 tusbhControlSendSetup(pdevice, (uint8_t *)&pdevice->setupPacket, pdevice->cntl_pipe_out);
301 pdevice->cstate = CONTROL_SETUP_WAIT;
302 ercd = TUSBH_E_BUSY_URB;
303 break;
304 case CONTROL_SETUP_WAIT: /* PACKETセットアップ URB待ち */
305 if(mes[0] != TUSBH_URB_EVENT)
306 break;
307 if(URB_Status == TUSBH_URB_DONE){ /* 正常終了 */
308 uint8_t direction = (type & USB_REQUEST_DIR_MASK);
309 if(length != 0 ){
310 if(direction == USB_DEVICE_TO_HOST){ /* データREAD */
311 tusbhControlReceiveData(pdevice, pdevice->cbuff, length, pdevice->cntl_pipe_in);
312 pdevice->cstate = CONTROL_DATA_IN_WAIT;
313 }
314 else{ /* データWRITE */
315 tusbhControlSendData(pdevice, pdevice->cbuff, length, pdevice->cntl_pipe_out);
316 pdevice->cstate = CONTROL_DATA_OUT_WAIT;
317 }
318 }
319 else{ /* ステータス通信 */
320 if(direction == USB_DEVICE_TO_HOST){ /* ステータス受信 */
321 tusbhControlSendData(pdevice, 0, 0, pdevice->cntl_pipe_out);
322 pdevice->cstate = CONTROL_STATUS_OUT_WAIT;
323 }
324 else{ /* ステータス送信 */
325 tusbhControlReceiveData(pdevice, 0, 0, pdevice->cntl_pipe_in);
326 pdevice->cstate = CONTROL_STATUS_IN_WAIT;
327 }
328 }
329 ercd = TUSBH_E_BUSY_URB;
330 }
331 else if(URB_Status == TUSBH_URB_ERROR) /* USBエラー */
332 pdevice->cstate = CONTROL_ERROR;
333 else if(URB_Status == TUSBH_URB_NOTREADY){
334 syslog_0(LOG_NOTICE, "### tusbhControlRequest REAET STATE1 ###");
335 pdevice->cstate = CONTROL_SETUP;
336 }
337 else{
338 syslog_2(LOG_ERROR, "tusbhControlRequest urb error state(%d) urb[%02x] !", pdevice->cstate, URB_Status);
339 ercd = TUSBH_E_URB;
340 }
341 break;
342 case CONTROL_DATA_IN_WAIT: /* データ受信待ち */
343 if(mes[0] != TUSBH_URB_EVENT)
344 break;
345 if(URB_Status == TUSBH_URB_DONE){ /* 正常終了 */
346 tusbhControlSendData(pdevice, 0, 0, pdevice->cntl_pipe_out);
347 pdevice->cstate = CONTROL_STATUS_OUT_WAIT;
348 ercd = TUSBH_E_BUSY_URB;
349 }
350 else if(URB_Status == TUSBH_URB_STALL){ /* ステール状態 */
351 pdevice->cstate = CONTROL_IDLE;
352 ercd = TUSBH_E_NOSPT;
353 }
354 else if(URB_Status == TUSBH_URB_ERROR) /* URBエラー */
355 pdevice->cstate = CONTROL_ERROR;
356 else if(URB_Status == TUSBH_URB_NOTREADY){
357 syslog_0(LOG_NOTICE, "### tusbhControlRequest REAET STATE2 ###");
358 pdevice->cstate = CONTROL_SETUP;
359 }
360 else{
361 syslog_2(LOG_ERROR, "tusbhControlRequest urb error state(%d) urb[%02x] !", pdevice->cstate, URB_Status);
362 ercd = TUSBH_E_URB;
363 }
364 break;
365 case CONTROL_DATA_OUT_WAIT: /* データ送信終了待ち */
366 if(mes[0] != TUSBH_URB_EVENT)
367 break;
368 if(URB_Status == TUSBH_URB_DONE){ /* 正常終了 */
369 tusbhControlReceiveData(pdevice, 0, 0, pdevice->cntl_pipe_in);
370 pdevice->cstate = CONTROL_STATUS_IN_WAIT;
371 ercd = TUSBH_E_BUSY_URB;
372 }
373 else if(URB_Status == TUSBH_URB_STALL){ /* ステール状態 */
374 pdevice->cstate = CONTROL_IDLE;
375 ercd = TUSBH_E_NOSPT;
376 }
377 else if(URB_Status == TUSBH_URB_NOTREADY){
378 /* Nack received from device */
379 tusbhControlSendData(pdevice, pdevice->cbuff, length, pdevice->cntl_pipe_out);
380 ercd = TUSBH_E_BUSY_URB;
381 }
382 else if(URB_Status == TUSBH_URB_ERROR) /* USBエラー */
383 pdevice->cstate = CONTROL_ERROR;
384 else{
385 syslog_2(LOG_ERROR, "tusbhControlRequest urb error state(%d) urb[%02x] !", pdevice->cstate, URB_Status);
386 ercd = TUSBH_E_URB;
387 }
388 break;
389 case CONTROL_STATUS_IN_WAIT: /* ステータス送信待ち */
390 if(mes[0] != TUSBH_URB_EVENT)
391 break;
392 if(URB_Status == TUSBH_URB_DONE){ /* 正常終了 */
393 pdevice->cstate = CONTROL_IDLE;
394 ercd = TUSBH_E_OK;
395 tusbSendData(phost->process_event, TUSBH_PORT_EVENT, pdevice->idx, 0, 0);
396 }
397 else if(URB_Status == TUSBH_URB_ERROR) /* USBエラー */
398 pdevice->cstate = CONTROL_ERROR;
399 else if(URB_Status == TUSBH_URB_STALL){ /* ステール状態 */
400 pdevice->cstate = CONTROL_IDLE;
401 ercd = TUSBH_E_NOSPT;
402 }
403 else if(URB_Status == TUSBH_URB_NOTREADY){
404 syslog_0(LOG_NOTICE, "### tusbhControlRequest REAET STATE3 ###");
405 pdevice->cstate = CONTROL_SETUP;
406 }
407 else{
408 syslog_2(LOG_ERROR, "tusbhControlRequest urb error state(%d) urb[%02x] !", pdevice->cstate, URB_Status);
409 ercd = TUSBH_E_URB;
410 }
411 break;
412 case CONTROL_STATUS_OUT_WAIT: /* ステータス受信待ち */
413 if(mes[0] != TUSBH_URB_EVENT)
414 break;
415 if(URB_Status == TUSBH_URB_DONE){
416 pdevice->cstate = CONTROL_IDLE;
417 ercd = TUSBH_E_OK;
418 tusbSendData(phost->process_event, TUSBH_PORT_EVENT, pdevice->idx, 0, 0);
419 }
420 else if(URB_Status == TUSBH_URB_NOTREADY){
421 tusbhControlSendData(pdevice, 0, 0, pdevice->cntl_pipe_out);
422 ercd = TUSBH_E_BUSY_URB;
423 }
424 else if(URB_Status == TUSBH_URB_ERROR) /* USBエラー */
425 pdevice->cstate = CONTROL_ERROR;
426 else{
427 syslog_2(LOG_ERROR, "tusbhControlRequest urb error state(%d) urb[%02x] !", pdevice->cstate, URB_Status);
428 ercd = TUSBH_E_URB;
429 }
430 break;
431 case CONTROL_ERROR:
432 /*
433 * コントロール通信エラーケース
434 * エラーカウントが TUSBH_MAX_ERROR_COUNT以下ならばリトライする
435 */
436 if(++pdevice->cntl_errcount <= TUSBH_MAX_ERROR_COUNT){
437 if(pdevice->hub == 0)
438 tusbhHDStop(phost);
439 else
440 tusbhResetHub(pdevice);
441 /*
442 * リトライする
443 */
444 pdevice->cstate = CONTROL_SETUP;
445 }
446 else{
447 if(phost->usrcallback != NULL)
448 phost->usrcallback(phost, pdevice, HOST_USER_UNRECOVERED_ERROR);
449 pdevice->cntl_errcount = 0;
450 syslog_1(LOG_ERROR, "tusbhControlRequest error count(%d) !", pdevice->cntl_errcount);
451 ercd = TUSBH_E_ERR;
452 }
453 break;
454 default:
455 break;
456 }
457 return ercd;
458}
459
Note: See TracBrowser for help on using the repository browser.