source: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/MSC/tusbh_msc.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: 28.3 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 MSC CLASS部
40 */
41
42#include "tusbh_msc.h"
43
44
45typedef enum {
46 BOT_OK,
47 BOT_BUSY,
48 BOT_SENSE,
49 BOT_ERROR
50} BOT_TYPE;
51
52#define CBW_SIGNATURE 0x43425355
53#define CSW_SIGNATURE 0x53425355
54#define CBW_TAG 0x20304050
55
56#define BOT_CBW_LENGTH 31 /* CBW送信パケット長 */
57#define BOT_CSW_LENGTH 13 /* CSW受信パケット長 */
58
59#define UNIT_READY_TIMEOUT (10000)
60
61#define BOT_REQUEST_GETMAXLUN(d, b) tusbhControlRequest((d), (b), BOT_REQUEST_GETMAXLUN_TYPE, USB_REQ_GET_MAX_LUN, 0, 0, 1)
62#define BOT_REQUEST_RESET(d) tusbhControlRequest((d), 0, BOT_REQUEST_RESET_TYPE, USB_REQ_BOT_RESET, 0, 0, 0)
63
64
65/*
66 * SENSEデータ
67 */
68typedef struct
69{
70 uint8_t key;
71 uint8_t asc;
72 uint8_t ascq;
73} SCSI_Sense_t;
74
75
76static TUSBH_ERCODE tusbhMSCInit(TUSBH_Device_t *pdevice);
77static TUSBH_ERCODE tusbhMSCDeInit(TUSBH_Device_t *pdevice);
78static TUSBH_ERCODE tusbhMSCProcess(TUSBH_Device_t *pdevice, uint8_t *mes);
79
80static TUSBH_Class_t MSC_Class = {
81 NULL,
82 "MSC",
83 MSC_CLASS,
84 tusbhMSCInit,
85 tusbhMSCDeInit,
86 tusbhMSCProcess,
87 NULL
88};
89
90/*
91 * MSCクラスセットアップ関数
92 */
93void tusbhLinkMSC(TUSBH_Handle_t *phost)
94{
95 tusbhLinkClass(phost, &MSC_Class);
96}
97
98/*
99 * MSC SCSI Inquiry要求
100 * parameter1 hmcs: MSCハンドラ
101 * parameter2 lun: LUN#
102 * return TUSBH_E_BUSY
103 */
104static TUSBH_ERCODE
105tusbhMscSCSIInquiry(MSC_Handle_t *hmsc, uint8_t lun)
106{
107 hmsc->hbot.cbw.DataTransferLength = DATA_LEN_INQUIRY;
108 hmsc->hbot.cbw.Flags = USB_DEVICE_TO_HOST;
109 hmsc->hbot.cbw.CBLength = CBW_LENGTH;
110
111 tusbmemset(hmsc->hbot.cbw.CB, 0, CBW_LENGTH);
112 hmsc->hbot.cbw.CB[0] = OPCODE_INQUIRY;
113 hmsc->hbot.cbw.CB[1] = (lun << 5);
114 hmsc->hbot.cbw.CB[2] = 0;
115 hmsc->hbot.cbw.CB[3] = 0;
116 hmsc->hbot.cbw.CB[4] = 0x24;
117 hmsc->hbot.cbw.CB[5] = 0;
118
119 hmsc->hbot.state = BOT_SEND_CBW;
120 hmsc->hbot.pbuf = (uint8_t *)hmsc->hbot.data;
121 return TUSBH_E_BUSY;
122}
123
124/*
125 * MSC SCSI Test Unit Ready要求
126 * parameter1 hmcs: MSCハンドラ
127 * parameter2 lun: LUN#
128 * return TUSBH_E_BUSY
129 */
130static TUSBH_ERCODE
131tusbhMscSCSITestUnitReady(MSC_Handle_t *hmsc, uint8_t lun)
132{
133 hmsc->hbot.cbw.DataTransferLength = DATA_LEN_MODE_TEST_UNIT_READY;
134 hmsc->hbot.cbw.Flags = USB_HOST_TO_DEVICE;
135 hmsc->hbot.cbw.CBLength = CBW_LENGTH;
136
137 tusbmemset(hmsc->hbot.cbw.CB, 0, CBW_CB_LENGTH);
138 hmsc->hbot.cbw.CB[0] = OPCODE_TEST_UNIT_READY;
139
140 hmsc->hbot.state = BOT_SEND_CBW;
141 return TUSBH_E_BUSY;
142}
143
144/*
145 * MSC SCSI Read Capacity要求
146 * parameter1 hmcs: MSCハンドラ
147 * parameter2 lun: LUN#
148 * return TUSBH_E_BUSY
149 */
150static TUSBH_ERCODE
151tusbhMscSCSIReadCapacity(MSC_Handle_t *hmsc, uint8_t lun)
152{
153 hmsc->hbot.cbw.DataTransferLength = DATA_LEN_READ_CAPACITY10;
154 hmsc->hbot.cbw.Flags = USB_DEVICE_TO_HOST;
155 hmsc->hbot.cbw.CBLength = CBW_LENGTH;
156
157 tusbmemset(hmsc->hbot.cbw.CB, 0, CBW_CB_LENGTH);
158 hmsc->hbot.cbw.CB[0] = OPCODE_READ_CAPACITY10;
159
160 hmsc->hbot.state = BOT_SEND_CBW;
161 hmsc->hbot.pbuf = (uint8_t *)hmsc->hbot.data;
162 return TUSBH_E_BUSY;
163}
164
165/*
166 * MSC SCSI Request Sense要求
167 * parameter1 hmcs: MSCハンドラ
168 * parameter2 lun: LUN#
169 * return TUSBH_E_BUSY
170 */
171static TUSBH_ERCODE
172tusbhMscSCSIRequestSense(MSC_Handle_t *hmsc, uint8_t lun)
173{
174 hmsc->hbot.cbw.DataTransferLength = DATA_LEN_REQUEST_SENSE;
175 hmsc->hbot.cbw.Flags = USB_DEVICE_TO_HOST;
176 hmsc->hbot.cbw.CBLength = CBW_LENGTH;
177
178 tusbmemset(hmsc->hbot.cbw.CB, 0, CBW_CB_LENGTH);
179 hmsc->hbot.cbw.CB[0] = OPCODE_REQUEST_SENSE;
180 hmsc->hbot.cbw.CB[1] = (lun << 5);
181 hmsc->hbot.cbw.CB[2] = 0;
182 hmsc->hbot.cbw.CB[3] = 0;
183 hmsc->hbot.cbw.CB[4] = DATA_LEN_REQUEST_SENSE;
184 hmsc->hbot.cbw.CB[5] = 0;
185
186 hmsc->hbot.state = BOT_SEND_CBW;
187 hmsc->hbot.pbuf = (uint8_t *)hmsc->hbot.data;
188 return TUSBH_E_BUSY;
189}
190
191/*
192 * SCCI データ転送
193 * parameter1 hmcs: MSCハンドラ
194 * parameter2 mes: メッセージへのポインタ
195 * parameter3 lun: LUN#
196 * return BOT_TYPE
197 */
198static BOT_TYPE
199tusbhMscSCSITransfer(MSC_Handle_t *hmsc, uint8_t *mes, uint8_t lun)
200{
201 TUSBH_Device_t *pdevice = hmsc->pDev;
202 TUSBH_Handle_t *phost;
203 BOT_TYPE status = BOT_BUSY;
204 TUSBH_ERCODE ercd = TUSBH_E_BUSY;
205 TUSBH_URBState_t URB_Status = mes[3];
206 uint8_t toggle = 0;
207
208 phost = pdevice->pHost;
209 switch (hmsc->hbot.state){
210 case BOT_SEND_CBW:
211 hmsc->hbot.cbw.LUN = lun;
212 hmsc->hbot.state = BOT_SEND_CBW_WAIT;
213 tusbhBulkWrite(pdevice, (uint8_t *)&hmsc->hbot.cbw, BOT_CBW_LENGTH, hmsc->OutPipe);
214 break;
215
216 case BOT_SEND_CBW_WAIT:
217 if(mes[0] != TUSBH_URB_EVENT)
218 break;
219 if(URB_Status == TUSBH_URB_DONE){
220 if(hmsc->hbot.cbw.DataTransferLength != 0){
221 if(((hmsc->hbot.cbw.Flags) & USB_REQUEST_DIR_MASK) == USB_DEVICE_TO_HOST){
222 /*
223 * BOT DATA INケース
224 */
225 tusbhBulkRead (pdevice, hmsc->hbot.pbuf, hmsc->InEpSize, hmsc->InPipe);
226 hmsc->hbot.state = BOT_DATA_IN_WAIT;
227 }
228 else{
229 /*
230 * BOT DATA OUTケース
231 */
232 tusbhBulkWrite(pdevice, hmsc->hbot.pbuf, hmsc->OutEpSize, hmsc->OutPipe);
233 hmsc->hbot.state = BOT_DATA_OUT_WAIT;
234 }
235 }
236 else{
237 /*
238 * ステータス通信ケース
239 */
240 tusbhBulkRead(pdevice, (uint8_t *)&hmsc->hbot.csw, BOT_CSW_LENGTH, hmsc->InPipe);
241 hmsc->hbot.state = BOT_RECEIVE_CSW_WAIT;
242 }
243 }
244 else if(URB_Status == TUSBH_URB_NOTREADY){
245 /*
246 * CBWを再送
247 */
248 hmsc->hbot.state = BOT_SEND_CBW;
249 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
250 }
251 else if(URB_Status == TUSBH_URB_STALL){
252 /*
253 * Clear Fuature Out Endpoint(CBWSTALL)
254 */
255 ercd = tusbhClearFeature(pdevice, hmsc->OutEp);
256 if(ercd == TUSBH_E_OK){
257 toggle = tusbhHDGetToggle(phost, hmsc->OutPipe);
258 tusbhHDSetToggle(phost, hmsc->OutPipe, 1- toggle);
259 tusbhHDSetToggle(phost, hmsc->InPipe, 0);
260 /*
261 * Clear Fuature In Endpoint
262 */
263 ercd = tusbhClearFeature(pdevice, hmsc->InEp);
264 if(ercd == TUSBH_E_OK){
265 tusbhBulkRead(pdevice, (uint8_t *)&hmsc->hbot.csw, BOT_CSW_LENGTH, hmsc->InPipe);
266 hmsc->hbot.state = BOT_RECEIVE_CSW_WAIT;
267 }
268 else
269 hmsc->hbot.state = BOT_STATE_ERROR;
270 }
271 else
272 hmsc->hbot.state = BOT_STATE_ERROR;
273 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
274 }
275 break;
276
277 case BOT_DATA_IN_WAIT:
278 if(mes[0] != TUSBH_URB_EVENT)
279 break;
280 if(URB_Status == TUSBH_URB_DONE){
281 /*
282 * 受信データ長アップデート
283 */
284 if(hmsc->hbot.cbw.DataTransferLength > hmsc->InEpSize){
285 hmsc->hbot.pbuf += hmsc->InEpSize;
286 hmsc->hbot.cbw.DataTransferLength -= hmsc->InEpSize;
287 }
288 else
289 hmsc->hbot.cbw.DataTransferLength = 0;
290 if(hmsc->hbot.cbw.DataTransferLength > 0){
291 /*
292 * 次のパケット要求
293 */
294 tusbhBulkRead(pdevice, hmsc->hbot.pbuf, hmsc->InEpSize, hmsc->InPipe);
295 }
296 else{
297 /*
298 * 受信終了、CSW受信要求
299 */
300 tusbhBulkRead(pdevice, (uint8_t *)&hmsc->hbot.csw, BOT_CSW_LENGTH, hmsc->InPipe);
301 hmsc->hbot.state = BOT_RECEIVE_CSW_WAIT;
302 }
303 }
304 else if(URB_Status == TUSBH_URB_STALL){
305 /*
306 * Clear Fuature In Endpoint(受信STALL)
307 */
308 ercd = tusbhClearFeature(pdevice, hmsc->InEp);
309 if(ercd == TUSBH_E_OK){
310 tusbhBulkRead(pdevice, (uint8_t *)&hmsc->hbot.csw, BOT_CSW_LENGTH, hmsc->InPipe);
311 hmsc->hbot.state = BOT_RECEIVE_CSW_WAIT;
312 }
313 else
314 hmsc->hbot.state = BOT_STATE_ERROR;
315 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
316 }
317 break;
318
319 case BOT_DATA_OUT_WAIT:
320 if(mes[0] != TUSBH_URB_EVENT)
321 break;
322 if(URB_Status == TUSBH_URB_DONE){
323 /*
324 * 送信データ長アップデート
325 */
326 if(hmsc->hbot.cbw.DataTransferLength > hmsc->OutEpSize){
327 hmsc->hbot.pbuf += hmsc->OutEpSize;
328 hmsc->hbot.cbw.DataTransferLength -= hmsc->OutEpSize;
329 }
330 else
331 hmsc->hbot.cbw.DataTransferLength = 0;
332 if(hmsc->hbot.cbw.DataTransferLength > 0){
333 /*
334 * 次のパケット送信
335 */
336 tusbhBulkWrite(pdevice, hmsc->hbot.pbuf, hmsc->OutEpSize, hmsc->OutPipe);
337 }
338 else{
339 /*
340 * 送信終了、CSW受信要求
341 */
342 tusbhBulkRead(pdevice, (uint8_t *)&hmsc->hbot.csw, BOT_CSW_LENGTH, hmsc->InPipe);
343 hmsc->hbot.state = BOT_RECEIVE_CSW_WAIT;
344 }
345 }
346 else if(URB_Status == TUSBH_URB_NOTREADY){
347 /*
348 * 再送設定
349 */
350 tusbhBulkWrite(pdevice, hmsc->hbot.pbuf, hmsc->OutEpSize, hmsc->OutPipe);
351 hmsc->hbot.state = BOT_DATA_OUT_WAIT;
352 }
353 else if(URB_Status == TUSBH_URB_STALL){
354 /*
355 * Clear Fuature Out Endpoint(送信STALL)
356 */
357 ercd = tusbhClearFeature(pdevice, hmsc->OutEp);
358 if(ercd == TUSBH_E_OK){
359 toggle = tusbhHDGetToggle(phost, hmsc->OutPipe);
360 tusbhHDSetToggle(phost, hmsc->OutPipe, 1- toggle);
361 tusbhHDSetToggle(phost, hmsc->InPipe, 0);
362 /*
363 * Clear Fuature In Endpoint
364 */
365 ercd = tusbhClearFeature(pdevice, hmsc->InEp);
366 if(ercd == TUSBH_E_OK){
367 tusbhBulkRead(pdevice, (uint8_t *)&hmsc->hbot.csw, BOT_CSW_LENGTH, hmsc->InPipe);
368 hmsc->hbot.state = BOT_RECEIVE_CSW_WAIT;
369 }
370 else
371 hmsc->hbot.state = BOT_STATE_ERROR;
372 }
373 else
374 hmsc->hbot.state = BOT_STATE_ERROR;
375 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
376 }
377 break;
378
379 case BOT_RECEIVE_CSW_WAIT:
380 if(mes[0] != TUSBH_URB_EVENT)
381 break;
382 if(URB_Status == TUSBH_URB_DONE){
383 hmsc->hbot.state = BOT_SEND_CBW;
384 if(hmsc->hbot.csw.Signature != CSW_SIGNATURE)
385 status = BOT_ERROR;
386 else if(hmsc->hbot.csw.Status == 0)
387 status = BOT_OK;
388 else if(hmsc->hbot.csw.Status == 1){
389#if 1 /* ROI DEBUG */
390 syslog_1(LOG_NOTICE, "## SBH_MSC_BOT_Process BOT_RECEIVE_CSW_WAIT ERROR CSW_Status(%d) ##", hmsc->hbot.csw.Status);
391#endif /* ROI DEBUG */
392 status = BOT_SENSE;
393 }
394 else
395 status = BOT_ERROR;
396 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
397 }
398 else if(URB_Status == TUSBH_URB_STALL){
399 /*
400 * Clear Fuature In Endpoint(CSW-STALL)
401 */
402 ercd = tusbhClearFeature(pdevice, hmsc->InEp);
403 if(ercd == TUSBH_E_OK){
404 tusbhBulkRead(pdevice, (uint8_t *)&hmsc->hbot.csw, BOT_CSW_LENGTH, hmsc->InPipe);
405 hmsc->hbot.state = BOT_RECEIVE_CSW_WAIT;
406 }
407 else
408 hmsc->hbot.state = BOT_STATE_ERROR;
409 tusbSendData (phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
410 }
411 break;
412
413 case BOT_STATE_ERROR:
414 BOT_REQUEST_RESET(pdevice);
415 hmsc->hbot.state = BOT_STATE_ERROR_WAIT;
416 break;
417
418 case BOT_STATE_ERROR_WAIT:
419 if((ercd = tusbhControlWait(pdevice, mes)) == TUSBH_E_OK)
420 hmsc->hbot.state = BOT_SEND_CBW;
421 else if(ercd != TUSBH_E_BUSY && ercd != TUSBH_E_BUSY_URB)
422 status = BOT_ERROR;
423 break;
424
425 default:
426 break;
427 }
428 return status;
429}
430
431/*
432 * MSC SCSI Disk Initialize
433 * parameter1 hmcs: MSCハンドラ
434 * parameter2 lun: LUN#
435 * return TUSBH_E_BUSY
436 */
437static TUSBH_ERCODE
438tusbhMscSCSIDiskInitailize(MSC_Handle_t *hmsc, uint8_t *mes, uint8_t lun)
439{
440 MSC_Unit_t *punit = &hmsc->unit[lun];
441 SCSI_Sense_t sense;
442 TUSBH_ERCODE status = TUSBH_E_OK;
443 BOT_TYPE bot_status = BOT_BUSY;
444
445 switch (punit->state){
446 case MSC_UNIT_INIT:
447 syslog_1(LOG_NOTICE, "[MSC]LUN : #%d", lun);
448 punit->state = MSC_UNIT_READ_INQUIRY_WAIT;
449 status = tusbhMscSCSIInquiry(hmsc, lun);
450 case MSC_UNIT_READ_INQUIRY_WAIT:
451 bot_status = tusbhMscSCSITransfer(hmsc, mes, lun);
452 if(bot_status == BOT_OK){
453 /*
454 * INQUIRY情報取得
455 */
456 punit->DeviceType = hmsc->hbot.pbuf[0] & 0x1F;
457 punit->PeripheralQualifier = hmsc->hbot.pbuf[0] >> 5;
458 punit->RemovableMedia = (hmsc->hbot.pbuf[1] & 0x80)== 0x80;
459 tusbmemcpy(punit->vendor_id, &hmsc->hbot.pbuf[8], 8);
460 tusbmemcpy(punit->product_id, &hmsc->hbot.pbuf[16], 16);
461 tusbmemcpy(punit->revision_id, &hmsc->hbot.pbuf[32], 4);
462
463 syslog_1(LOG_NOTICE, "[MSC]Inquiry Vendor : %s", punit->vendor_id);
464 syslog_1(LOG_NOTICE, "[MSC]Inquiry Product : %s", punit->product_id);
465 syslog_1(LOG_NOTICE, "[MSC]Inquiry Version : %s", punit->revision_id);
466 punit->state = MSC_UNIT_TEST_UNIT_READY_WAIT;
467 status = tusbhMscSCSITestUnitReady(hmsc, lun);
468 }
469 else if(bot_status == BOT_SENSE){
470 punit->state = MSC_UNIT_REQUEST_SENSE_WAIT;
471 punit->pre_state = MSC_UNIT_READ_INQUIRY_WAIT;
472 status = tusbhMscSCSIRequestSense(hmsc, lun);
473 }
474 else if(bot_status == BOT_ERROR){
475 punit->state = MSC_UNIT_ERROR;
476 }
477 else{
478 dly_tsk(10);
479 if(++hmsc->urb_wait > 500)
480 punit->state = MSC_UNIT_ERROR;
481 }
482 break;
483 case MSC_UNIT_TEST_UNIT_READY_WAIT:
484 bot_status = tusbhMscSCSITransfer(hmsc, mes, lun);
485 if(bot_status == BOT_OK){
486 syslog_1(LOG_NOTICE, "[MSC] Device ready(%d) !", lun);
487 punit->state = MSC_UNIT_READ_CAPACITY_WAIT;
488 status = tusbhMscSCSIReadCapacity(hmsc, lun);
489 }
490 else if(bot_status == BOT_SENSE){
491 if(hmsc->timer >= UNIT_READY_TIMEOUT){
492 syslog_1(LOG_NOTICE, "[MSC] Device NOT ready(%d) !", lun);
493 }
494 punit->state = MSC_UNIT_REQUEST_SENSE_WAIT;
495 punit->pre_state = MSC_UNIT_TEST_UNIT_READY_WAIT;
496 status = tusbhMscSCSIRequestSense(hmsc, lun);
497 }
498 else if(bot_status == BOT_ERROR){
499 punit->state = MSC_UNIT_ERROR;
500 }
501 else{
502 dly_tsk(10);
503 if(++hmsc->urb_wait > 500)
504 punit->state = MSC_UNIT_ERROR;
505 }
506 break;
507 case MSC_UNIT_READ_CAPACITY_WAIT:
508 bot_status = tusbhMscSCSITransfer(hmsc, mes, lun);
509 if(bot_status == BOT_OK){
510 /*
511 * ユニット容量を取得
512 */
513 punit->num_block = hmsc->hbot.pbuf[3] | (hmsc->hbot.pbuf[2] << 8) |
514 (hmsc->hbot.pbuf[1] << 16) | (hmsc->hbot.pbuf[0] << 24);
515 punit->block_size = hmsc->hbot.pbuf[7] | (hmsc->hbot.pbuf[6] << 8);
516 syslog_1(LOG_NOTICE, "[MSC] Device capacity : %u Bytes", \
517 (uint32_t)(punit->num_block * punit->block_size));
518 syslog_1(LOG_NOTICE, " Block number : %u", (uint32_t)(punit->num_block));
519 syslog_1(LOG_NOTICE, " Block Size : %u", (uint32_t)(punit->block_size));
520 punit->state = MSC_UNIT_IDLE;
521 hmsc->lun++;
522 }
523 else if(bot_status == BOT_SENSE){
524 punit->state = MSC_UNIT_REQUEST_SENSE_WAIT;
525 punit->pre_state = MSC_UNIT_READ_CAPACITY_WAIT;
526 status = tusbhMscSCSIRequestSense(hmsc, lun);
527 }
528 else if(bot_status == BOT_ERROR){
529 punit->state = MSC_UNIT_ERROR;
530 }
531 else{
532 dly_tsk(10);
533 if(++hmsc->urb_wait > 500)
534 punit->state = MSC_UNIT_ERROR;
535 }
536 break;
537 case MSC_UNIT_REQUEST_SENSE_WAIT:
538 bot_status = tusbhMscSCSITransfer(hmsc, mes, lun);
539 if(bot_status == BOT_OK){
540 sense.key = hmsc->hbot.pbuf[2] & 0x0F;
541 sense.asc = hmsc->hbot.pbuf[12];
542 sense.ascq = hmsc->hbot.pbuf[13];
543 if(sense.key == SCSI_SENSE_KEY_UNIT_ATTENTION || sense.key == SCSI_SENSE_KEY_NOT_READY){
544 if(hmsc->timer < UNIT_READY_TIMEOUT){
545 if(punit->pre_state == MSC_UNIT_READ_INQUIRY_WAIT){
546 punit->state = MSC_UNIT_READ_INQUIRY_WAIT;
547 status = tusbhMscSCSIInquiry(hmsc, lun);
548 break;
549 }
550 else if(punit->pre_state == MSC_UNIT_TEST_UNIT_READY_WAIT){
551 punit->state = MSC_UNIT_TEST_UNIT_READY_WAIT;
552 status = tusbhMscSCSITestUnitReady(hmsc, lun);
553 break;
554 }
555 else if(punit->pre_state == MSC_UNIT_READ_CAPACITY_WAIT){
556 punit->state = MSC_UNIT_READ_CAPACITY_WAIT;
557 status = tusbhMscSCSIReadCapacity(hmsc, lun);
558 break;
559 }
560 }
561 }
562 syslog_1(LOG_NOTICE, "[MSC] Sense Key : %x", sense.key);
563 syslog_1(LOG_NOTICE, "[MSC] Additional Sense Code : %x", sense.asc);
564 syslog_1(LOG_NOTICE, "[MSC] Additional Sense Code Qualifier: %x", sense.ascq);
565 punit->state = MSC_UNIT_IDLE;
566 lun++;
567 }
568 else if(bot_status == BOT_SENSE || bot_status == BOT_ERROR){
569 punit->state = MSC_UNIT_ERROR;
570 }
571 else{
572 dly_tsk(10);
573 if(++hmsc->urb_wait > 500)
574 punit->state = MSC_UNIT_ERROR;
575 }
576 break;
577 case MSC_UNIT_ERROR:
578 hmsc->lun++;
579 break;
580 default:
581 break;
582 }
583 return status;
584}
585
586
587/*
588 * MSCクラス初期設定
589 * parameter1 pdevice: デバイスハンドラ
590 * return TUSBH_ERCODE
591 */
592static TUSBH_ERCODE
593tusbhMSCInit(TUSBH_Device_t *pdevice)
594{
595 uint8_t interface = 0;
596 TUSBH_ERCODE status = TUSBH_E_ERR ;
597 MSC_Handle_t *hmsc;
598 TUSBH_Handle_t *phost = pdevice->pHost;
599 uint8_t max_ep, i;
600
601 interface = tusbhFindInterface(pdevice, pdevice->pClass->classCode, MSC_TRANSPARENT_SUBCLASS, MSC_BOT_PROTOCOL);
602
603 if(interface == NO_INTERFACE){
604 syslog_1(LOG_ERROR, "[MSC] Cannot Find the interface for %s class.", pdevice->pClass->Name);
605 return TUSBH_E_ERR;
606 }
607 tusbhSelectInterface(pdevice, interface);
608
609 hmsc = (MSC_Handle_t *)tusbmalloc(sizeof(MSC_Handle_t));
610 pdevice->pData = hmsc;
611 memset(hmsc, 0, sizeof(MSC_Handle_t));
612 max_ep = ((pdevice->ItfDesc[pdevice->sel_interface].bNumEndpoints <= 2) ?
613 pdevice->ItfDesc[pdevice->sel_interface].bNumEndpoints : 2);
614
615 for(i = 0 ; i < max_ep; i++){
616 if(pdevice->EpDesc[pdevice->sel_interface][i].bEndpointAddress & 0x80){
617 hmsc->InEp = (pdevice->EpDesc[pdevice->sel_interface][i].bEndpointAddress);
618 hmsc->InEpSize = pdevice->EpDesc[pdevice->sel_interface][i].wMaxPacketSize;
619 hmsc->InPipe = tusbhAllocPipe(phost, hmsc->InEp);
620 }
621 else{
622 hmsc->OutEp = (pdevice->EpDesc[pdevice->sel_interface][i].bEndpointAddress);
623 hmsc->OutEpSize = pdevice->EpDesc[pdevice->sel_interface][i].wMaxPacketSize;
624 hmsc->OutPipe = tusbhAllocPipe(phost, hmsc->OutEp);
625 }
626 }
627 if(hmsc->OutPipe == 0 || hmsc->InPipe == 0)
628 return TUSBH_E_ERR;
629
630 hmsc->lun = 0;
631 hmsc->state = MSC_PROCESS_INIT;
632 hmsc->urb_wait = 0;
633 hmsc->timer = 0;
634 hmsc->pDev = pdevice;
635
636 hmsc->hbot.cbw.Signature = CBW_SIGNATURE;
637 hmsc->hbot.cbw.Tag = CBW_TAG;
638 hmsc->hbot.state = BOT_SEND_CBW;
639
640 /*
641 * NSCチャネルオープン
642 */
643 tusbhOpenPipe(pdevice, hmsc->OutPipe, hmsc->OutEp, USB_EP_TYPE_BULK, hmsc->OutEpSize);
644 tusbhHDSetToggle(phost, hmsc->OutPipe, 0);
645 tusbhOpenPipe(pdevice, hmsc->InPipe, hmsc->InEp, USB_EP_TYPE_BULK, hmsc->InEpSize);
646 tusbhHDSetToggle(phost, hmsc->InPipe, 0);
647
648 /*
649 * 最大LUNを取得
650 */
651 status = BOT_REQUEST_GETMAXLUN(pdevice, ((uint8_t *)&hmsc->hbot.data));
652 hmsc->max_lun = hmsc->hbot.data[0];
653
654 /*
655 * NO SUPPORT受信の場合、0を設定
656 */
657 if(status == TUSBH_E_NOSPT){
658 hmsc->max_lun = 0;
659 status = TUSBH_E_OK;
660 }
661
662 /*
663 * UNIT領域の初期化
664 */
665 if(status == TUSBH_E_OK){
666 uint32_t i;
667 hmsc->max_lun = (uint8_t )(hmsc->max_lun) + 1;
668 syslog_1(LOG_NOTICE, "[MSC] Number of supported LUN: %d", (int32_t)(hmsc->max_lun));
669
670 for(i = 0; i < hmsc->max_lun; i++){
671 tusbmemset(&hmsc->unit[i], 0, sizeof(hmsc->unit));
672 hmsc->unit[i].state = MSC_UNIT_INIT;
673 }
674 }
675 pdevice->numUnit = hmsc->max_lun;
676 /* タイマースタート */
677 pdevice->timeid = pdevice->timecount = 100;
678 return TUSBH_E_OK;
679}
680
681/*
682 * MSCクラス終了設定
683 * parameter1 pdevice: デバイスハンドラ
684 * return TUSBH_ERCODE
685 */
686static TUSBH_ERCODE
687tusbhMSCDeInit(TUSBH_Device_t *pdevice)
688{
689 MSC_Handle_t *hmsc;
690 TUSBH_Handle_t *phost = pdevice->pHost;
691
692 hmsc = (MSC_Handle_t *)pdevice->pData;
693 if(hmsc->OutPipe != 0){
694 tusbhClosePipe(pdevice, hmsc->OutPipe);
695 tusbFreePipe(phost, hmsc->OutPipe);
696 hmsc->OutPipe = 0;
697 }
698
699 if(hmsc->InPipe != 0){
700 tusbhClosePipe(pdevice, hmsc->InPipe);
701 tusbFreePipe(phost, hmsc->InPipe);
702 hmsc->InPipe = 0;
703 }
704
705 if(pdevice->pData != NULL){
706 tusbfree(pdevice->pData);
707 pdevice->pData = NULL;
708 }
709 return TUSBH_E_OK;
710}
711
712/*
713 * MSCクラスプロセス実行
714 * parameter1 pdevice: デバイスハンドラ
715 * parameter2 mes: 通信メッセージへのポインタ
716 * return TUSBH_ERCODE
717 */
718static TUSBH_ERCODE
719tusbhMSCProcess(TUSBH_Device_t *pdevice, uint8_t *mes)
720{
721 MSC_Handle_t *hmsc;
722 MSC_Unit_t *punit;
723 TUSBH_Handle_t *phost = pdevice->pHost;
724 TUSBH_ERCODE status = TUSBH_E_OK;
725 BOT_TYPE bot_status = BOT_BUSY;
726
727 hmsc = (MSC_Handle_t *)pdevice->pData;
728 if(mes[0] == TUSBH_URB_EVENT){
729 hmsc->urb_wait = 0;
730 }
731 else if(mes[0] == TUSBH_TIME_EVENT){
732 hmsc->timer += mes[3];
733 pdevice->timecount = mes[3];
734 }
735 switch (hmsc->state){
736 case MSC_PROCESS_INIT:
737 if(hmsc->lun < hmsc->max_lun){
738 status = tusbhMscSCSIDiskInitailize(hmsc, mes, hmsc->lun);
739 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
740 }
741 else{
742 hmsc->lun = 0;
743 hmsc->state = MSC_PROCESS_IDLE;
744 if(phost->usrcallback != NULL)
745 phost->usrcallback(phost, pdevice, HOST_USER_CLASS_ACTIVE);
746 }
747 break;
748 case MSC_PROCESS_READ_WAIT:
749 case MSC_PROCESS_WRITE_WAIT:
750 if(hmsc->lun >= hmsc->max_lun)
751 break;
752 punit = &hmsc->unit[hmsc->lun];
753 if(punit->rw_status == TUSBH_E_BUSY){
754 bot_status = tusbhMscSCSITransfer(hmsc, mes, hmsc->lun);
755 if(bot_status == BOT_SENSE){
756 hmsc->state = MSC_PROCESS_REQUEST_SENSE_WAIT;
757 tusbhMscSCSIRequestSense(hmsc, hmsc->lun);
758 tusbSendData( phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
759 }
760 else if(bot_status == BOT_ERROR){
761 punit->rw_status = TUSBH_E_ERR;
762 }
763 else if(bot_status != BOT_BUSY){
764 punit->rw_status = TUSBH_E_OK;
765 if(punit->rw_taskid != 0)
766 tusbWakeup(punit->rw_taskid);
767 }
768 }
769 break;
770 case MSC_PROCESS_REQUEST_SENSE_WAIT:
771 if(hmsc->lun >= hmsc->max_lun)
772 break;
773 punit = &hmsc->unit[hmsc->lun];
774 if(punit->rw_status == TUSBH_E_BUSY){
775 bot_status = tusbhMscSCSITransfer(hmsc, mes, hmsc->lun);
776 if(bot_status == BOT_OK){
777 punit->rw_status = TUSBH_E_OK;
778 if(punit->rw_taskid != 0)
779 tusbWakeup(punit->rw_taskid);
780 }
781 else if(bot_status != BOT_BUSY){
782 punit->rw_status = TUSBH_E_ERR;
783 }
784 }
785 break;
786 case MSC_PROCESS_IDLE:
787 status = TUSBH_E_OK;
788 break;
789 default:
790 break;
791 }
792 return status;
793}
794
795/*
796 * ユニット READY確認
797 * parameter1 phost: ホストハンドラ
798 * parameter2 lun: unit#
799 * return status: (0: not ready / 1: ready)
800 */
801uint8_t
802tusbhMscUnitIsReady(TUSBH_Handle_t *phost, uint8_t lun)
803{
804 TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, MSC_Class.classCode, &lun);
805 MSC_Handle_t *hmsc;
806
807 if(pdevice == NULL)
808 return 0;
809 hmsc = (MSC_Handle_t *)pdevice->pData;
810
811 if(pdevice->dstate == DEVICE_CLASS)
812 return (hmsc->unit[lun].state >= MSC_UNIT_IDLE);
813 else
814 return 0;
815}
816
817/*
818 * ユニット情報を取得
819 * parameter1 phost: ホストハンドラ
820 * parameter2 lun: unit#
821 * parameter3 info: ユニット取得領域へのポインタ
822 * return TUSBH_ERCODE
823 */
824TUSBH_ERCODE
825tusbhMscGetLUNInfo(TUSBH_Handle_t *phost, uint8_t lun, MSC_Unit_t *info)
826{
827 TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, MSC_Class.classCode, &lun);
828 MSC_Handle_t *hmsc;
829
830 if(pdevice == NULL)
831 return TUSBH_E_OBJ;
832 hmsc = (MSC_Handle_t *) pdevice->pData;
833
834 if(pdevice->dstate == DEVICE_CLASS){
835 tusbmemcpy(info, &hmsc->unit[lun], sizeof(MSC_Unit_t));
836 return TUSBH_E_OK;
837 }
838 else
839 return TUSBH_E_OBJ;
840}
841
842/*
843 * MSC BLOCK READ
844 * parameter1 phost: ホストハンドラ
845 * parameter2 lun: unit#
846 * parameter3 address: ユニットアドレス
847 * parameter4 pbuf: 受信データ領域へのポインタ
848 * parameter5 num: 受信ブロック数
849 * return TUSBH_ERCODE
850 */
851TUSBH_ERCODE
852tusbhMscRead(TUSBH_Handle_t *phost, uint8_t lun, uint32_t address, uint8_t *pbuf, uint32_t num)
853{
854 TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, MSC_Class.classCode, &lun);
855 MSC_Handle_t *hmsc;
856 TUSBH_ERCODE status = TUSBH_E_BUSY;
857 uint32_t i;
858
859 if(pdevice != NULL){
860 hmsc = pdevice->pData;
861 if(pdevice->dstate != DEVICE_CLASS || hmsc->unit[lun].state != MSC_UNIT_IDLE)
862 return TUSBH_E_OBJ;
863 }
864 else
865 return TUSBH_E_OBJ;
866 if(lun >= hmsc->max_lun)
867 return TUSBH_E_PAR;
868
869 hmsc->state = MSC_PROCESS_READ_WAIT;
870 hmsc->unit[lun].rw_status = TUSBH_E_BUSY;
871 hmsc->unit[lun].rw_taskid = tusbGetTaskID();
872 hmsc->unit[lun].state = MSC_UNIT_READ_WAIT;
873 hmsc->lun = lun;
874
875 /*
876 * BLOCK READ CBW設定
877 */
878 hmsc->hbot.cbw.DataTransferLength = num * 512;
879 hmsc->hbot.cbw.Flags = USB_DEVICE_TO_HOST;
880 hmsc->hbot.cbw.CBLength = CBW_LENGTH;
881 tusbmemset(hmsc->hbot.cbw.CB, 0, CBW_CB_LENGTH);
882 hmsc->hbot.cbw.CB[0] = OPCODE_READ10;
883
884 hmsc->hbot.cbw.CB[2] = (address >> 24) & 0xff;
885 hmsc->hbot.cbw.CB[3] = (address >> 16) & 0xff;
886 hmsc->hbot.cbw.CB[4] = (address >> 8) & 0xff;
887 hmsc->hbot.cbw.CB[5] = address & 0xff;
888
889 hmsc->hbot.cbw.CB[7] = (num >> 8) & 0xff;
890 hmsc->hbot.cbw.CB[8] = num & 0xff;
891
892 hmsc->hbot.state = BOT_SEND_CBW;
893 hmsc->hbot.pbuf = pbuf;
894 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
895
896 for(i = 0 ; i < (num * 1000) ; i++){
897 tusbSleep(50);
898 if((status = hmsc->unit[lun].rw_status) != TUSBH_E_BUSY)
899 break;
900 }
901 if(status == TUSBH_E_BUSY)
902 status = TUSBH_E_TMOUT;
903 hmsc->unit[lun].rw_taskid = 0;
904 hmsc->unit[lun].state = MSC_UNIT_IDLE;
905 hmsc->state = MSC_PROCESS_IDLE;
906 return status;
907}
908
909/*
910 * MSC BLOCK WRITE
911 * parameter1 phost: ホストハンドラ
912 * parameter2 lun: unit#
913 * parameter3 address: ユニットアドレス
914 * parameter4 pbuf: 送信データ領域へのポインタ
915 * parameter5 num: 送信ブロック数
916 * return TUSBH_ERCODE
917 */
918TUSBH_ERCODE
919tusbhMscWrite(TUSBH_Handle_t *phost, uint8_t lun, uint32_t address, uint8_t *pbuf, uint32_t num)
920{
921 TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, MSC_Class.classCode, &lun);
922 MSC_Handle_t *hmsc;
923 TUSBH_ERCODE status = TUSBH_E_BUSY;
924 uint32_t i;
925
926 if(pdevice != NULL){
927 hmsc = pdevice->pData;
928 if(pdevice->dstate != DEVICE_CLASS || hmsc->unit[lun].state != MSC_UNIT_IDLE)
929 return TUSBH_E_OBJ;
930 }
931 else
932 return TUSBH_E_OBJ;
933 if(lun >= hmsc->max_lun)
934 return TUSBH_E_PAR;
935
936 hmsc->state = MSC_PROCESS_WRITE_WAIT;
937 hmsc->unit[lun].rw_taskid = tusbGetTaskID();
938 hmsc->unit[lun].rw_status = TUSBH_E_BUSY;
939 hmsc->unit[lun].state = MSC_UNIT_WRITE_WAIT;
940 hmsc->lun = lun;
941
942 /*
943 * BLOCK WRITE CBW設定
944 */
945 hmsc->hbot.cbw.DataTransferLength = num * 512;
946 hmsc->hbot.cbw.Flags = USB_HOST_TO_DEVICE;
947 hmsc->hbot.cbw.CBLength = CBW_LENGTH;
948 tusbmemset(hmsc->hbot.cbw.CB, 0, CBW_CB_LENGTH);
949 hmsc->hbot.cbw.CB[0] = OPCODE_WRITE10;
950
951 hmsc->hbot.cbw.CB[2] = (address >> 24) & 0xff;
952 hmsc->hbot.cbw.CB[3] = (address >> 16) & 0xff;
953 hmsc->hbot.cbw.CB[4] = (address >> 8) & 0xff;
954 hmsc->hbot.cbw.CB[5] = (((uint8_t*)&address)[0]);
955
956 hmsc->hbot.cbw.CB[7] = (num >> 8) & 0xff;
957 hmsc->hbot.cbw.CB[8] = num & 0xff;
958
959 hmsc->hbot.state = BOT_SEND_CBW;
960 hmsc->hbot.pbuf = pbuf;
961 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
962
963 for(i = 0 ; i < (num * 1000) ; i++){
964 tusbSleep(50);
965 if((status = hmsc->unit[lun].rw_status) != TUSBH_E_BUSY)
966 break;
967 }
968 if(status == TUSBH_E_BUSY)
969 status = TUSBH_E_TMOUT;
970 hmsc->unit[lun].rw_taskid = 0;
971 hmsc->unit[lun].state = MSC_UNIT_IDLE;
972 hmsc->state = MSC_PROCESS_IDLE;
973 return status;
974}
975
976
Note: See TracBrowser for help on using the repository browser.