source: azure_iot_hub_f767zi/trunk/asp_baseplatform/usb/host/PRT/tusbh_prt.c@ 457

Last change on this file since 457 was 457, 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: 14.5 KB
Line 
1/*
2 * TOPPERS BASE PLATFORM MIDDLEWARE
3 *
4 * Copyright (C) 2017-2018 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 PRT CLASS部
40 */
41
42#include "tusbh_prt.h"
43
44
45#define CONTROL_STATUS 1
46#define CONTROL_VENDER 2
47
48
49#define PRT_REQUEST_VENDER(d, b, c, l) tusbhControlRequest((d), (b), PRT_VENDER_SEND_TYPE, (c), 0, 0, (l))
50#define PRT_REQUEST_STATUS(d, b, c, l) tusbhControlRequest((d), (b), PRT_REQUEST_STATUS_TYPE, (c), 0, 0, (l))
51
52
53static TUSBH_ERCODE tusbhPRTInit(TUSBH_Device_t *pdevice);
54static TUSBH_ERCODE tusbhPRTDeInit(TUSBH_Device_t *pdevice);
55static TUSBH_ERCODE tusbhPRTProcess(TUSBH_Device_t *pdevice, uint8_t *mes);
56
57static TUSBH_Class_t PRT_Class = {
58 NULL,
59 "PRT",
60 PRT_CLASS,
61 tusbhPRTInit,
62 tusbhPRTDeInit,
63 tusbhPRTProcess,
64 NULL
65};
66
67/*
68 * PRTクラスセットアップ関数
69 */
70void tusbhLinkPRT(TUSBH_Handle_t *phost)
71{
72 tusbhLinkClass(phost, &PRT_Class);
73}
74
75/*
76 * PRTクラス初期設定
77 * parameter1 pdevice: デバイスハンドラ
78 * return TUSBH_ERCODE
79 */
80static TUSBH_ERCODE
81tusbhPRTInit(TUSBH_Device_t *pdevice)
82{
83 uint8_t interface = 0;
84 PRT_Handle_t *hprt;
85 TUSBH_Handle_t *phost = pdevice->pHost;
86 uint8_t max_ep, i;
87
88 interface = tusbhFindInterface(pdevice, pdevice->pClass->classCode, 0x01, 0x02);
89
90 if(interface == NO_INTERFACE){
91 syslog_1(LOG_ERROR, "[PRT] Cannot Find the interface for %s class.", pdevice->pClass->Name);
92 return TUSBH_E_ERR;
93 }
94 tusbhSelectInterface(pdevice, interface);
95
96 hprt = (PRT_Handle_t *)tusbmalloc(sizeof(PRT_Handle_t));
97 pdevice->pData = hprt;
98 memset(hprt, 0, sizeof(PRT_Handle_t));
99 max_ep = ((pdevice->ItfDesc[interface].bNumEndpoints <= 2) ?
100 pdevice->ItfDesc[interface].bNumEndpoints : 2);
101#if 1 /* ROI DEBUG */
102 syslog_3(LOG_NOTICE, "## tusbhPRTInit hmsc[%08x] max_ep(%d) buffer(%d) ##", hprt, max_ep, offsetof(PRT_Handle_t, buffer));
103#endif /* ROI DEBUG */
104
105 for(i = 0 ; i < max_ep; i++){
106 if(pdevice->EpDesc[interface][i].bEndpointAddress & 0x80){
107 hprt->InEp = (pdevice->EpDesc[interface][i].bEndpointAddress);
108 hprt->InEpSize = pdevice->EpDesc[interface][i].wMaxPacketSize;
109 hprt->InPipe = tusbhAllocPipe(phost, hprt->InEp);
110 }
111 else{
112 hprt->OutEp = (pdevice->EpDesc[interface][i].bEndpointAddress);
113 hprt->OutEpSize = pdevice->EpDesc[interface][i].wMaxPacketSize;
114 hprt->OutPipe = tusbhAllocPipe(phost, hprt->OutEp);
115 }
116 }
117 if(hprt->OutPipe == 0 || hprt->InPipe == 0)
118 return TUSBH_E_ERR;
119
120 hprt->state = PRT_PROCESS_INIT;
121 hprt->timer = 0;
122 hprt->pDev = pdevice;
123
124 /*
125 * NSCチャネルオープン
126 */
127 tusbhOpenPipe(pdevice, hprt->OutPipe, hprt->OutEp, USB_EP_TYPE_BULK, hprt->OutEpSize);
128 tusbhHDSetToggle(phost, hprt->OutPipe, 0);
129 tusbhOpenPipe(pdevice, hprt->InPipe, hprt->InEp, USB_EP_TYPE_BULK, hprt->InEpSize);
130 tusbhHDSetToggle(phost, hprt->InPipe, 0);
131
132 /* タイマースタート */
133 pdevice->timeid = pdevice->timecount = 100;
134 return TUSBH_E_OK;
135}
136
137/*
138 * PRTクラス終了設定
139 * parameter1 pdevice: デバイスハンドラ
140 * return TUSBH_ERCODE
141 */
142static TUSBH_ERCODE
143tusbhPRTDeInit(TUSBH_Device_t *pdevice)
144{
145 PRT_Handle_t *hprt;
146 TUSBH_Handle_t *phost = pdevice->pHost;
147
148 hprt = (PRT_Handle_t *)pdevice->pData;
149 if(hprt->OutPipe != 0){
150 tusbhClosePipe(pdevice, hprt->OutPipe);
151 tusbFreePipe(phost, hprt->OutPipe);
152 hprt->OutPipe = 0;
153 }
154
155 if(hprt->InPipe != 0){
156 tusbhClosePipe(pdevice, hprt->InPipe);
157 tusbFreePipe(phost, hprt->InPipe);
158 hprt->InPipe = 0;
159 }
160
161 if(pdevice->pData != NULL){
162 tusbfree(pdevice->pData);
163 pdevice->pData = NULL;
164 }
165 return TUSBH_E_OK;
166}
167
168/*
169 * PRTクラスプロセス実行
170 * parameter1 pdevice: デバイスハンドラ
171 * parameter2 mes: 通信メッセージへのポインタ
172 * return TUSBH_ERCODE
173 */
174static TUSBH_ERCODE
175tusbhPRTProcess(TUSBH_Device_t *pdevice, uint8_t *mes)
176{
177 PRT_Handle_t *hprt = (PRT_Handle_t *)pdevice->pData;
178 TUSBH_Handle_t *phost = pdevice->pHost;
179 void (*func)(TUSBH_Device_t *, uint8_t, TUSBH_ERCODE, uint32_t) = pdevice->pClass->subfunc;
180 TUSBH_URBState_t URB_Status = mes[3];
181 TUSBH_ERCODE ercd = TUSBH_E_BUSY;
182 int32_t length;
183
184 if(mes[0] == TUSBH_URB_EVENT){
185 hprt->urb_wait = 0;
186 }
187 else if(mes[0] == TUSBH_TIME_EVENT){
188 hprt->timer += mes[3];
189 pdevice->timecount = mes[3];
190 }
191 else if(mes[0] == TUSBH_CLASS_EVENT && mes[2] != 0)
192 hprt->state = mes[2];
193 switch (hprt->state){
194 case PRT_PROCESS_INIT:
195 if(phost->usrcallback != NULL)
196 phost->usrcallback(phost, pdevice, HOST_USER_CLASS_ACTIVE);
197 hprt->state = PRT_PROCESS_IDLE;
198 case PRT_PROCESS_IDLE:
199 if(mes[0] != TUSBH_URB_EVENT){
200 ercd = TUSBH_E_OK;
201 break;
202 }
203 if(mes[2] == pdevice->cntl_pipe_in || mes[2] == pdevice->cntl_pipe_out){
204 ercd = tusbhControlWait(pdevice, mes);
205 if(ercd == TUSBH_E_OK){
206 hprt->state = PRT_PROCESS_IDLE;
207 hprt->controlType = 0;
208 }
209 else if(ercd != TUSBH_E_BUSY && ercd != TUSBH_E_BUSY_URB){
210 hprt->state = PRT_PROCESS_ERROR;
211 hprt->controlType = 0;
212 }
213 break;
214 }
215 else if(URB_Status == TUSBH_URB_DONE){
216 if(mes[2] == hprt->InPipe){
217 hprt->RxTrnPktSize = tusbhHDTrasLength(phost, hprt->InPipe);
218 hprt->RxTrnLength += hprt->RxTrnPktSize;
219 hprt->pRxTrnBuff += hprt->RxTrnPktSize;
220 hprt->rwr_status = TUSBH_E_OK;
221 if(func != NULL)
222 func(pdevice, PRT_LINE_STATUS_RECEIVED, TUSBH_E_OK, hprt->RxTrnLength);
223 }
224 else{
225 hprt->TxTrnLength += hprt->TxTrnPktSize;
226 hprt->pTxTrnBuff += hprt->TxTrnPktSize;
227 if(hprt->TxTrnSize > hprt->TxTrnLength)
228 hprt->state = PRT_PROCESS_SEND;
229 else{
230 hprt->rwt_status = TUSBH_E_OK;
231 if(func != NULL)
232 func(pdevice, PRT_LINE_STATUS_SENDED, TUSBH_E_OK, hprt->TxTrnLength);
233 }
234 }
235 }
236 else if(URB_Status == TUSBH_URB_NOTREADY){
237 if(mes[2] == hprt->InPipe)
238 hprt->state = PRT_PROCESS_RECEIVE;
239 else
240 hprt->state = PRT_PROCESS_SEND;
241 }
242 else{
243 hprt->state = PRT_PROCESS_ERROR;
244 if(mes[2] == hprt->InPipe)
245 hprt->rwr_status = TUSBH_E_ERR;
246 else
247 hprt->rwt_status = TUSBH_E_ERR;
248 if(func != NULL)
249 func(pdevice, PRT_LINE_STATUS_CHANGED, TUSBH_E_ERR, 0);
250 }
251 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
252 break;
253 case PRT_PROCESS_CONTROL:
254 if(hprt->controlType == CONTROL_VENDER)
255 PRT_REQUEST_VENDER(pdevice, hprt->buffer, hprt->controlRequest, hprt->controlLength);
256 else
257 PRT_REQUEST_STATUS(pdevice, hprt->buffer, hprt->controlRequest, hprt->controlLength);
258 hprt->state = PRT_PROCESS_IDLE;
259 break;
260 case PRT_PROCESS_SEND:
261 length = hprt->TxTrnSize - hprt->TxTrnLength;
262 if(length > hprt->OutEpSize)
263 hprt->TxTrnPktSize = hprt->OutEpSize;
264 else
265 hprt->TxTrnPktSize = length;
266 tusbhBulkWrite(pdevice, hprt->pTxTrnBuff, hprt->TxTrnPktSize, hprt->OutPipe);
267 hprt->state = PRT_PROCESS_IDLE;
268 break;
269 case PRT_PROCESS_RECEIVE:
270 length = hprt->RxTrnSize - hprt->RxTrnLength;
271 if(length > hprt->InEpSize)
272 hprt->RxTrnPktSize = hprt->InEpSize;
273 else
274 hprt->RxTrnPktSize = length;
275 tusbhBulkRead(pdevice, hprt->pRxTrnBuff, hprt->RxTrnPktSize, hprt->InPipe);
276 hprt->state = PRT_PROCESS_IDLE;
277 break;
278 case PRT_PROCESS_ERROR:
279 tusbhClearFeature(pdevice, 0x00);
280 hprt->state = PRT_PROCESS_ERROR_WAIT;
281 break;
282 case PRT_PROCESS_ERROR_WAIT:
283 if(tusbhControlWait(pdevice, mes) == TUSBH_E_OK)
284 hprt->state = PRT_PROCESS_IDLE;
285 break;
286
287
288 default:
289 break;
290 }
291 return ercd;
292}
293
294/*
295 * PRT SEND EOJ
296 * parameter1 phost: ホストハンドラ
297 * parameter2 unit: UNIT#
298 * parameter3 cmd: 設定コマンド
299 * return TUSBH_ERCODE
300 */
301TUSBH_ERCODE
302tusbhPrtEOJ(TUSBH_Handle_t *phost, uint8_t unit, uint8_t cmd, uint8_t prm1, uint8_t prm2)
303{
304 TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, PRT_Class.classCode, &unit);
305 PRT_Handle_t *hprt;
306
307 if(pdevice == NULL)
308 return TUSBH_E_OBJ;
309 hprt = (PRT_Handle_t *)pdevice->pData;
310 if(pdevice->dstate == DEVICE_CLASS){
311 hprt->buffer[0] = cmd;
312 hprt->buffer[1] = prm1;
313 hprt->buffer[2] = prm2;
314 hprt->controlType = CONTROL_VENDER;
315 hprt->controlRequest = PRT_VERNDER_REQUEST_EOJ;
316 hprt->controlLength = 3;
317 hprt->state = PRT_PROCESS_CONTROL;
318 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
319 while(hprt->controlType != 0){
320 tusbSleep(1);
321 }
322 }
323 return TUSBH_E_OK;
324}
325
326/*
327 * PRT GET PORTID
328 * parameter1 phost: ホストハンドラ
329 * parameter2 unit: UNIT#
330 * parameter3 cmd: 設定コマンド
331 * return TUSBH_ERCODE
332 */
333TUSBH_ERCODE
334tusbhPrtPortID(TUSBH_Handle_t *phost, uint8_t unit, uint8_t *buf)
335{
336 TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, PRT_Class.classCode, &unit);
337 PRT_Handle_t *hprt;
338
339 if(pdevice == NULL)
340 return TUSBH_E_OBJ;
341 hprt = (PRT_Handle_t *)pdevice->pData;
342 if(pdevice->dstate == DEVICE_CLASS){
343 hprt->controlType = CONTROL_STATUS;
344 hprt->controlRequest = PRT_REQUEST_DEVICEID;
345 hprt->controlLength = 1;
346 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, PRT_PROCESS_CONTROL, 0);
347 while(hprt->controlType != 0){
348 tusbSleep(1);
349 }
350 *buf = hprt->buffer[0];
351 }
352 return TUSBH_E_OK;
353}
354
355/*
356 * PRT GET PRINT STATUS
357 * parameter1 phost: ホストハンドラ
358 * parameter2 unit: UNIT#
359 * parameter3 cmd: 設定コマンド
360 * return TUSBH_ERCODE
361 */
362TUSBH_ERCODE
363tusbhPrtPortStatus(TUSBH_Handle_t *phost, uint8_t unit, uint8_t *buf, uint32_t length)
364{
365 TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, PRT_Class.classCode, &unit);
366 PRT_Handle_t *hprt;
367 uint32_t trans_len, packet_len;
368
369 if(length > PRT_MAX_PORTSTATUS_SIZE)
370 trans_len = PRT_MAX_PORTSTATUS_SIZE;
371 else
372 trans_len = length;
373 if(pdevice == NULL)
374 return TUSBH_E_OBJ;
375 hprt = (PRT_Handle_t *)pdevice->pData;
376 if(pdevice->dstate == DEVICE_CLASS){
377 hprt->controlType = CONTROL_STATUS;
378 hprt->controlRequest = PRT_REQUEST_PORTSTATUS;
379 hprt->controlLength = trans_len;
380 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, PRT_PROCESS_CONTROL, 0);
381 while(hprt->controlType != 0){
382 tusbSleep(1);
383 }
384 packet_len = (hprt->buffer[0] << 8) | hprt->buffer[1];
385 if(trans_len > (packet_len + 2))
386 trans_len = packet_len + 2;
387 tusbmemcpy(buf, hprt->buffer, trans_len);
388 }
389 return TUSBH_E_OK;
390}
391
392/*
393 * PRT DATA RECEIVE
394 * parameter1 phost: ホストハンドラ
395 * parameter2 unit: UNIT#
396 * parameter3 pbuf: 受信データ領域へのポインタ
397 * parameter4 length: 受信ブロック長
398 * return TUSBH_ERCODE
399 */
400TUSBH_ERCODE
401tusbhPrtReceive(TUSBH_Handle_t *phost, uint8_t unit, uint8_t *pbuf, uint32_t length)
402{
403 TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, PRT_Class.classCode, &unit);
404 PRT_Handle_t *hprt;
405
406 if(pdevice != NULL){
407 hprt = pdevice->pData;
408 if(pdevice->dstate != DEVICE_CLASS)
409 return TUSBH_E_OBJ;
410 if(hprt->state == PRT_PROCESS_ERROR)
411 return TUSBH_E_ERR;
412 if(hprt->rwr_status == TUSBH_E_BUSY)
413 return TUSBH_E_OBJ;
414 }
415 else
416 return TUSBH_E_OBJ;
417
418 /*
419 * 受信データ設定
420 */
421 hprt->RxTrnSize = length;
422 hprt->RxTrnLength = 0;
423 hprt->pRxTrnBuff = pbuf;
424 hprt->rwr_status = TUSBH_E_BUSY;
425 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, PRT_PROCESS_RECEIVE, 0);
426 return TUSBH_E_OK;
427}
428
429/*
430 * PRT DATA SEND
431 * parameter1 phost: ホストハンドラ
432 * parameter2 unit: UNIT#
433 * parameter3 pbuf: 送信データ領域へのポインタ
434 * parameter4 length: 送信データ長
435 * return TUSBH_ERCODE
436 */
437TUSBH_ERCODE
438tusbhPrtSend(TUSBH_Handle_t *phost, uint8_t unit, uint8_t *pbuf, uint32_t length)
439{
440 TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, PRT_Class.classCode, &unit);
441 PRT_Handle_t *hprt;
442
443 if(pdevice != NULL){
444 hprt = pdevice->pData;
445 if(pdevice->dstate != DEVICE_CLASS)
446 return TUSBH_E_OBJ;
447 if(hprt->state == PRT_PROCESS_ERROR)
448 return TUSBH_E_ERR;
449 if(hprt->rwt_status == TUSBH_E_BUSY)
450 return TUSBH_E_OBJ;
451 }
452 else
453 return TUSBH_E_OBJ;
454
455 /*
456 * 送信データ設定
457 */
458 hprt->TxTrnSize = length;
459 hprt->TxTrnLength = 0;
460 hprt->pTxTrnBuff = pbuf;
461 hprt->rwt_status = TUSBH_E_BUSY;
462 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, PRT_PROCESS_SEND, 0);
463 return TUSBH_E_OK;
464}
465
466/*
467 * PRTコールバック関数
468 * parameter1 phost: ホストハンドラ
469 * parameter2 func: 関数ポインタ
470 */
471void
472tusbhSetPrtCallBack(TUSBH_Handle_t *phost, void (*func)(TUSBH_Device_t *p, uint8_t, TUSBH_ERCODE, uint32_t))
473{
474 PRT_Class.subfunc = func;
475}
476
477
Note: See TracBrowser for help on using the repository browser.