source: azure_iot_hub_f767zi/trunk/asp_baseplatform/usb/host/tusbh_base.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: 30.9 KB
Line 
1/*
2 * TOPPERS BASE PLATFORM MIDDLEWARE
3 *
4 * Copyright (C) 2017-2019 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 BASE部
40 */
41
42#include "tusbh_base.h"
43
44
45#define USBH_ADDRESS_DEFAULT 0
46#define USBH_MPS_DEFAULT 0x40
47#define USBH_DEVICE_ADDRESS(d) ((d)->idx + 1)
48
49#define USBH_SET_CONFIGURATION(d, i) tusbhControlRequest((d), 0, SET_CONFIGURATION_TYPE, SET_CONFIGURATION, (i), 0, 0)
50#define USBH_SET_ADDRESS(d, a) tusbhControlRequest((d), 0, SET_ADDRESS_TYPE, SET_ADDRESS, (a), 0, 0)
51
52#ifndef CONNECT_WAIT_TIME
53#define CONNECT_WAIT_TIME 200
54#endif
55
56static TUSBH_Handle_t *usbh_arg;
57
58/*
59 * デバイスハンドラ初期化
60 */
61static void
62tusbhInitDevice(TUSBH_Device_t *pdevice)
63{
64 memset(pdevice->Data, 0, TUSBH_MAX_DATA_BUFFER);
65
66 pdevice->cntl_pipe_size = USBH_MPS_DEFAULT;
67 pdevice->cntl_errcount = 0;
68 pdevice->pClass = NULL;
69 pdevice->address = USBH_ADDRESS_DEFAULT;
70 pdevice->speed = USB_DEVICE_SPEED_FULL;
71 pdevice->dstate = DEVICE_IDLE;
72}
73
74/*
75 * アロケート・デバイスハンドラ
76 */
77static TUSBH_Device_t *
78tusbhAllocDevice(TUSBH_Handle_t *phost)
79{
80 TUSBH_Device_t *pdevice;
81 int i;
82
83 if(phost->numDevice >= MAX_DEVICE_CONNECTED)
84 return NULL;
85 if((pdevice = tusbmalloc(sizeof(TUSBH_Device_t))) == NULL)
86 return NULL;
87 memset(pdevice, 0, sizeof(TUSBH_Device_t));
88 if(phost->numDevice == 0)
89 phost->pDevice = pdevice;
90 else{
91 TUSBH_Device_t *pnext = phost->pDevice;
92 for(i = 1 ; i < phost->numDevice ; i++)
93 pnext = pnext->pNext;
94 pnext->pNext = pdevice;
95 }
96 pdevice->hub = 0xff;
97 pdevice->port = 0xff;
98 pdevice->pHost = phost;
99 pdevice->idx = phost->numDevice++;
100 tusbhInitDevice(pdevice);
101 return pdevice;
102}
103
104/*
105 * デバイスハンドラ検索
106 */
107static TUSBH_Device_t*
108tusbhFindDevice(TUSBH_Handle_t *phost, uint8_t idx)
109{
110 TUSBH_Device_t *pdevice = phost->pDevice;
111 uint8_t i;
112
113 for(i = 0 ; i < idx ; i++)
114 pdevice = pdevice->pNext;
115 return pdevice;
116}
117
118/*
119 * 有効デバイス数
120 */
121static uint8_t
122tusbActivateDevice(TUSBH_Handle_t *phost)
123{
124 TUSBH_Device_t *pdevice = phost->pDevice;
125 uint8_t i, actdevice = 0;
126
127 for(i = 0 ; i < phost->numDevice && pdevice != NULL ; i++){
128 if(pdevice->pClass != NULL)
129 actdevice++;
130 pdevice = pdevice->pNext;
131 }
132 return actdevice;
133}
134
135/*
136 * SEARCH DEVICE
137 * parameter1 phost: ホストハンドラ
138 * parameter2 classCide: クラスコード
139 * parameter3 plun: unit#
140 * return デバイスハンドラ
141 */
142TUSBH_Device_t *
143tusbhSearchDevice(TUSBH_Handle_t *phost, uint8_t classCode, uint8_t *plun)
144{
145 TUSBH_Device_t *pdevice = phost->pDevice;
146 uint8_t i;
147
148 for(i = 0 ; i < phost->numDevice && pdevice != NULL ; i++){
149 if(pdevice->type == classCode){
150 if(*plun < pdevice->numUnit)
151 break;
152 else
153 *plun -= pdevice->numUnit;
154 }
155 pdevice = pdevice->pNext;
156 }
157 return pdevice;
158}
159
160
161/*
162 * HC-PIPEのアロケート
163 * parameter1 pdevice: デバイスハンドラ
164 * parameter2 ep_addr: エンドポイントアドレス
165 * return PIPE番号(0xFFでエラー)
166 */
167uint8_t
168tusbhAllocPipe(TUSBH_Handle_t *phost, uint8_t ep_addr)
169{
170 uint8_t idx = 0;
171
172 for(idx = 0 ; idx < phost->numPipes ; idx++){
173 if((phost->pipes[idx].attribute & PIPE_ACTIVATE) == 0 && tusbhHDCheckPipe(phost, idx)){
174 phost->pipes[idx].attribute = PIPE_ACTIVATE | ep_addr;
175 return idx;
176 }
177 }
178 syslog_2(LOG_ERROR, "tusbhAllocPipe no free pipe [%08x] ep(%d) !", phost, ep_addr);
179 return 0xFF;
180}
181
182/*
183 * HC-PIPEの解放
184 * parameter1 pdevice: デバイスハンドラ
185 * parameter2 no: PIPE番号
186 * return TUSBH_ERCODE
187 */
188TUSBH_ERCODE
189tusbFreePipe(TUSBH_Handle_t *phost, uint8_t no)
190{
191 if(no < phost->numPipes){
192 phost->pipes[no].attribute &= ~PIPE_ACTIVATE;
193 }
194 return TUSBH_E_OK;
195}
196
197
198/*
199 * USBホスト初期化処理
200 * parameter1 phost: ホストハンドラ
201 * parameter2 pufunc:ユーザポインタ関数
202 * parameter3 id: USBホストID
203 * return TUSBH_ERCODE
204 */
205TUSBH_ERCODE
206tusbhInit(TUSBH_Handle_t *phost, void (*pufunc)(TUSBH_Handle_t *phost, TUSBH_Device_t *pdevice, uint8_t ), uint8_t id)
207{
208 uint8_t i;
209
210 /*
211 * USBホスト構造体の確認
212 */
213 if(phost == NULL){
214 syslog_0(LOG_ERROR, "Invalid Host handle !");
215 return TUSBH_E_PAR;
216 }
217
218 /*
219 * ホストIDをセット
220 */
221 phost->id = id;
222
223 /*
224 * リンクカウントを初期化
225 */
226 phost->numClass = 0;
227 phost->numDevice = 0;
228 phost->numHub = 0;
229
230 /*
231 * PIPEの初期化
232 */
233 for(i = 0 ; i < MAX_EPS_PIPES; i++){
234 phost->pipes[i].attribute = 0;
235 phost->pipes[i].index = 0;
236 }
237
238 /*
239 * ユーザー関数の保存
240 */
241 if(pufunc != NULL)
242 phost->usrcallback = pufunc;
243
244 /*
245 * タスク用にUSBホストハンドラを保存
246 */
247 usbh_arg = phost;
248
249 /*
250 * LOWレベルドライバの初期化
251 */
252 tusbhHDInit(phost);
253
254 /*
255 * タスクの起動
256 */
257 tusbStartTask(phost->eventTaskID);
258 tusbStartTask(phost->processTaskID);
259 return TUSBH_E_OK;
260}
261
262/*
263 * USBホスト終了処理
264 * parameter1 phost: ホストハンドラ
265 * return TUSBH_ERCODE
266 */
267TUSBH_ERCODE
268tusbhDeInit(TUSBH_Handle_t *phost)
269{
270 TUSBH_Device_t *pdevice;
271 uint8_t idx;
272
273 for(idx = 0, pdevice = phost->pDevice ; idx < phost->numDevice ; idx++){
274 tusbfree(pdevice);
275 pdevice = pdevice->pNext;
276 }
277 phost->pDevice = 0;
278
279 if(phost->pSysData != NULL){
280 tusbhHDStop(phost);
281 }
282 return TUSBH_E_OK;
283}
284
285/*
286 * クラス実行モジュールのリンク
287 * parameter1 phost: ホストハンドラ
288 * parameter2 pclass: クラス構造体へのポインタ
289 * return TUSBH_ERCODE
290 */
291TUSBH_ERCODE
292tusbhLinkClass(TUSBH_Handle_t *phost, TUSBH_Class_t *pclass)
293{
294 if(pclass == NULL)
295 return TUSBH_E_ERR;
296 pclass->pNext = NULL;
297 if(phost->numClass == 0)
298 phost->pClass = pclass;
299 else{
300 TUSBH_Class_t *pnext = phost->pClass;
301 uint32_t i;
302 for(i = 1 ; i < phost->numClass ; i++)
303 pnext = pnext->pNext;
304 pnext->pNext = pclass;
305 }
306 phost->numClass++;
307 return TUSBH_E_OK;
308}
309
310/*
311 * USBホスト開始
312 * parameter1 phost: ホストハンドラ
313 * return TUSBH_ERCODE
314 */
315TUSBH_ERCODE
316tusbhStart(TUSBH_Handle_t *phost)
317{
318 /*
319 * LOWレベルドライバをスタート
320 */
321 tusbhHDStart(phost);
322
323 /*
324 * VBUSを有効化
325 */
326 tusbhHDControlVBUS(phost, true);
327 return TUSBH_E_OK;
328}
329
330/*
331 * USBホスト停止
332 * parameter1 phost: ホストハンドラ
333 * return TUSBH_ERCODE
334 */
335TUSBH_ERCODE
336tusbhStop(TUSBH_Handle_t *phost)
337{
338 TUSBH_Device_t *pdevice = phost->pDevice;
339 uint8_t i = 0;
340
341 /*
342 * LOWレベルドライバ停止
343 */
344 tusbhHDStop(phost);
345
346 /*
347 * VBUSの停止
348 */
349 tusbhHDControlVBUS(phost, false);
350
351 /*
352 * PIPEの解放
353 */
354 for(i = 0 ; i < phost->numDevice && pdevice != NULL ; i++){
355 tusbFreePipe(phost, pdevice->cntl_pipe_in);
356 tusbFreePipe(phost, pdevice->cntl_pipe_out);
357 pdevice = pdevice->pNext;
358 }
359 return TUSBH_E_OK;
360}
361
362/*
363 * HUBのリセット要求
364 * parameter1 pdevice: デバイスハンドラ
365 * return TUSBH_ERCODE
366 */
367TUSBH_ERCODE
368tusbhResetHub(TUSBH_Device_t *pdevice)
369{
370 TUSBH_Handle_t *phost = pdevice->pHost;
371 TUSBH_Device_t *pdeviceh;
372 uint32_t idx;
373
374 syslog_2(LOG_ERROR, "tusbhResetHub hub(%d) port(%d) !", pdevice->hub, pdevice->port);
375 for(idx = 0, pdeviceh = phost->pDevice ; idx < phost->numDevice ; idx++){
376 if(pdevice->hub == pdeviceh->hubid){
377 tusbSendData(phost->process_event, TUSBH_RESET_EVENT, pdeviceh->idx, 0, pdevice->port);
378 break;
379 }
380 pdeviceh = pdeviceh->pNext;
381 }
382 return TUSBH_E_OK;
383}
384
385/*
386 * デバイスにインターフェイスを設定
387 * parameter1 pdevice: デバイスハンドラ
388 * parameter2 interface: インターフェイス値
389 * return TUSBH_ERCODE
390 */
391TUSBH_ERCODE
392tusbhSelectInterface(TUSBH_Device_t *pdevice, uint8_t interface)
393{
394 TUSBH_ERCODE ercd = TUSBH_E_OK;
395
396 if(interface < pdevice->CfgDesc.bNumInterfaces){
397 pdevice->sel_interface = interface;
398 syslog_2(LOG_NOTICE, "Switching to Interface device(%d) (#%d)", pdevice->idx, interface);
399 syslog_1(LOG_NOTICE, "Class : 0x%02x", pdevice->ItfDesc[interface].bInterfaceClass );
400 syslog_1(LOG_NOTICE, "SubClass : 0x%02x", pdevice->ItfDesc[interface].bInterfaceSubClass );
401 syslog_1(LOG_NOTICE, "Protocol : 0x%02x", pdevice->ItfDesc[interface].bInterfaceProtocol );
402 }
403 else{
404 syslog_1(LOG_ERROR, "Cannot Select This Interface (%d) !", pdevice->idx);
405 ercd = TUSBH_E_ERR;
406 }
407 return ercd;
408}
409
410/*
411 * クラス番号を取得
412 * parameter1 pdevice: デバイスハンドラ
413 * return Class code
414 */
415uint8_t
416tusbhGetActiveClass(TUSBH_Device_t *pdevice)
417{
418 return (pdevice->ItfDesc[0].bInterfaceClass);
419}
420
421/*
422 * クラス情報からインターフェイスのインデックスを返す
423 * parameter1 pdevice: デバイスハンドラ
424 * parameter2 Class: Class code
425 * parameter3 SubClass:Sub Class code
426 * parameter4 Protocal:Protocol code
427 * return interface index(ない場合はNO_INTERFACE)
428 */
429uint8_t
430tusbhFindInterface(TUSBH_Device_t *pdevice, uint8_t Class, uint8_t SubClass, uint8_t Protocol)
431{
432 InterfaceDescriptor *pif = NULL;
433 int8_t if_ix = 0;
434
435 while(if_ix < TUSBH_MAX_NUM_INTERFACES){
436 pif = &pdevice->ItfDesc[if_ix];
437 if((pif->bInterfaceClass == Class || Class == 0xFF) &&
438 (pif->bInterfaceSubClass == SubClass || SubClass == 0xFF) &&
439 (pif->bInterfaceProtocol == Protocol || Protocol == 0xFF)){
440 return if_ix;
441 }
442 if_ix++;
443 }
444 return NO_INTERFACE;
445}
446
447/*
448 * インターフェイス情報からインターフェイスのインデックスを返す
449 * parameter1 pdevice: デバイスハンドラ
450 * parameter2 interface: interface number
451 * parameter3 altsetnum: alternate setting #
452 * return interface index(ない場合は0xff)
453 */
454uint8_t
455tusbhFindInterfacebynumber(TUSBH_Device_t *pdevice, uint8_t interface, uint8_t altsetno)
456{
457 InterfaceDescriptor *pif = NULL;
458 int8_t if_ix = 0;
459
460 while (if_ix < TUSBH_MAX_NUM_INTERFACES){
461 pif = &pdevice->ItfDesc[if_ix];
462 if((pif->bInterfaceNumber == interface) && (pif->bAlternateSetting == altsetno)){
463 return if_ix;
464 }
465 if_ix++;
466 }
467 return 0xFF;
468}
469
470/*
471 * OPEN PIPE
472 * parameter1 pdevice: デバイスハンドラ
473 * parameter2 pipe: PIPE#
474 * parameter3 epnum: EP番号
475 * parameter5 type: エンドポイントタイプ
476 * parameter6 eps: MAXパケットサイズ
477 * return TUSBH_ERCODE
478 */
479TUSBH_ERCODE
480tusbhOpenPipe(TUSBH_Device_t *pdevice, uint8_t pipe, uint8_t epnum, uint8_t type, uint16_t mps)
481{
482 TUSBH_Handle_t *phost = pdevice->pHost;
483
484 phost->pipes[pipe].type = type;
485 return tusbhHDOpenPipe(phost, pipe, epnum, pdevice->address, pdevice->speed, type, mps);
486}
487
488/*
489 * CLOSE PIPE
490 * parameter1 pdevice: デバイスハンドラ
491 * parameter2 pipe: PIPE#
492 * return TUSBH_ERCODE
493 */
494TUSBH_ERCODE
495tusbhClosePipe(TUSBH_Device_t *pdevice, uint8_t pipe)
496{
497 return tusbhHDClosePipe(pdevice->pHost, pipe);
498}
499
500/*
501 * SUBMIT URB
502 * parameter1 pdevice: デバイスハンドラ
503 * parameter2 pipe: パイプ番号
504 * parameter3 type: SUBMITタイプ
505 * parameter4 eptype: エンドポイントタイプ
506 * parameter5 buff: データ領域へのポインタ
507 * parameter6 length: データ長
508 * return TUSBH_ERCODE
509 */
510TUSBH_ERCODE
511tusbhSubmitURB(TUSBH_Device_t *pdevice, uint8_t pipe, uint16_t type, uint8_t eptype, uint8_t* buff, uint16_t length)
512{
513 TUSBH_Handle_t *phost = pdevice->pHost;
514 uint8_t dir, token;
515 uint8_t do_ping = 0;
516
517 phost->pipes[pipe].index = pdevice->idx;
518 if(eptype != phost->pipes[pipe].type){
519 syslog_3(LOG_ERROR, "tusbhSubmitURB EPTYPE ERROR pipe(%d) rtype(%d) ctype(%d) !", pipe, eptype, phost->pipes[pipe].type);
520 return TUSBH_E_ERR;
521 }
522 if(eptype == USB_EP_TYPE_BULK || eptype == USB_EP_TYPE_CTRL){
523 if(pdevice->speed == USB_DEVICE_SPEED_HIGH && type == SUBMIT_WRITE)
524 do_ping = 1;
525 }
526 dir = type >> 8;
527 token = type & 0xff;
528 return tsubhHDSubmitURB(phost, pipe, dir, token, buff, length, do_ping);
529}
530
531/*
532 * Device Descriporコマンドをデバイスに送信し取得する
533 * parameter1 pdevice: デバイスハンドラ
534 * parameter2 length: Descripor長
535 * return TUSBH_ERCODE
536 */
537static TUSBH_ERCODE
538tusbhGetDeviceDescriptor(TUSBH_Device_t *pdevice, uint8_t length)
539{
540 TUSBH_ERCODE ercd;
541 volatile uint8_t *buff = pdevice->Data;
542 DeviceDescriptor *dev_desc = &pdevice->DevDesc;
543
544 if((ercd = tusbhGetDescriptor(pdevice,
545 USB_RECIPIENT_DEVICE | USB_REQUEST_TYPE_STANDARD,
546 ((DEVICE_DESCRIPTOR << 8) & 0xFF00),
547 (uint8_t *)buff,
548 length)) == TUSBH_E_OK){
549 /*
550 * DEVICE DESCRIPTER取得
551 */
552 dev_desc->bLength = buff[0];
553 dev_desc->bDescriptorType = buff[1];
554 dev_desc->bcdUSB = (buff[2] & 0xff) | (buff[3] << 8);
555 dev_desc->bDeviceClass = buff[4];
556 dev_desc->bDeviceSubClass = buff[5];
557 dev_desc->bDeviceProtocol = buff[6];
558 dev_desc->bMaxPacketSize = buff[7];
559
560 if(length > 8){ /* For 1st time after device connection, Host may issue only 8 bytes for Device Descriptor Length */
561 dev_desc->idVendor = (buff[8] & 0xff) | (buff[9] << 8);
562 dev_desc->idProduct = (buff[10] & 0xff) | (buff[11] << 8);
563 dev_desc->bcdDevice = (buff[12] & 0xff) | (buff[12] << 8);
564 dev_desc->iManufacturer = buff[14];
565 dev_desc->iProduct = buff[15];
566 dev_desc->iSerialNumber = buff[16];
567 dev_desc->bNumConfigurations = buff[17];
568 }
569 }
570 return ercd;
571}
572
573/*
574 * Config Descriporコマンドをデバイスに送信し取得する
575 * parameter1 pdevice: デバイスハンドラ
576 * parameter2 length: Descripor長
577 * return TUSBH_ERCODE
578 */
579static TUSBH_ERCODE
580tusbhGetConfigDescriptor(TUSBH_Device_t *pdevice, uint16_t length)
581{
582 ConfigurationDescriptor *cfg_desc = &pdevice->CfgDesc;
583 TUSBH_Handle_t *phost = pdevice->pHost;
584 volatile uint8_t *pdbuff;
585 TUSBH_ERCODE ercd;
586
587 if(phost->pCfgData != NULL)
588 pdbuff = (volatile uint8_t *)phost->pCfgData;
589 else
590 pdbuff = (volatile uint8_t *)pdevice->Data;
591 if((ercd = tusbhGetDescriptor(pdevice,
592 USB_RECIPIENT_DEVICE | USB_REQUEST_TYPE_STANDARD,
593 ((CONFIGURATION_DESCRIPTOR << 8) & 0xFF00),
594 (uint8_t *)pdbuff,
595 length)) == TUSBH_E_OK){
596
597 /*
598 * CONFIGURATION DESCRIPTOR設定
599 */
600 cfg_desc->bLength = pdbuff[0];
601 cfg_desc->bDescriptorType = pdbuff[1];
602 cfg_desc->wTotalLength = (pdbuff[2] & 0xff) | (pdbuff[3] << 8);
603 cfg_desc->bNumInterfaces = pdbuff[4];
604 cfg_desc->bConfigurationValue = pdbuff[5];
605 cfg_desc->iConfiguration = pdbuff[6];
606 cfg_desc->bmAttributes = pdbuff[7];
607 cfg_desc->bMaxPower = pdbuff[8];
608
609 if (length > CONFIGURATION_DESCRIPTOR_LENGTH){
610 uint16_t ptr = CONFIGURATION_DESCRIPTOR_LENGTH;
611 int8_t if_ix = 0;
612 int8_t ep_ix = 0;
613
614 while(if_ix < TUSBH_MAX_NUM_INTERFACES && ptr < cfg_desc->wTotalLength){
615 ptr += pdbuff[0];
616 pdbuff = (volatile uint8_t *)(pdbuff + pdbuff[0]);
617 if(pdbuff[1] == INTERFACE_DESCRIPTOR){
618 InterfaceDescriptor *pif = &pdevice->ItfDesc[if_ix];
619 /*
620 * INTERFACE DESCRIPTOR設定
621 */
622 pif->bLength = pdbuff[0];
623 pif->bDescriptorType = pdbuff[1];
624 pif->bInterfaceNumber = pdbuff[2];
625 pif->bAlternateSetting = pdbuff[3];
626 pif->bNumEndpoints = pdbuff[4];
627 pif->bInterfaceClass = pdbuff[5];
628 pif->bInterfaceSubClass = pdbuff[6];
629 pif->bInterfaceProtocol = pdbuff[7];
630 pif->iInterface = pdbuff[8];
631
632 ep_ix = 0;
633 while ((ep_ix < pif->bNumEndpoints) && (ptr < cfg_desc->wTotalLength)){
634 ptr += pdbuff[0];
635 pdbuff = (volatile uint8_t *)(pdbuff + pdbuff[0]);
636 if(pdbuff[1] == ENDPOINT_DESCRIPTOR){
637 EndpointDescriptor *pep = &pdevice->EpDesc[if_ix][ep_ix];
638 /*
639 * ENDPOINT DESCRIPTOR設定
640 */
641 pep->bLength = pdbuff[0];
642 pep->bDescriptorType = pdbuff[1];
643 pep->bEndpointAddress = pdbuff[2];
644 pep->bmAttributes = pdbuff[3];
645 pep->wMaxPacketSize = (pdbuff[4] & 0xff) | (pdbuff[5] << 8);
646 pep->bInterval = pdbuff[6];
647 ep_ix++;
648 }
649 }
650 if_ix++;
651 }
652 }
653 }
654 }
655 return ercd;
656}
657
658/*
659 * String Descriporコマンドをデバイスに送信
660 * parameter1 pdevice: デバイスハンドラ
661 * parameter2 string_index: String index
662 * parameter3 buff: 取り出し用のバッファ領域
663 * parameter4 length: Descripor長
664 * return TUSBH_ERCODE
665 */
666static TUSBH_ERCODE
667tusbhGetStringDescriptor(TUSBH_Device_t *pdevice,
668 uint8_t string_index,
669 uint8_t *buff,
670 uint16_t length)
671{
672 uint8_t *psrc = pdevice->Data;
673 TUSBH_ERCODE ercd;
674
675 if((ercd = tusbhGetDescriptor(pdevice,
676 USB_RECIPIENT_DEVICE | USB_REQUEST_TYPE_STANDARD,
677 ((STRING_DESCRIPTOR << 8) & 0xFF00) | string_index,
678 psrc,
679 length)) == TUSBH_E_OK){
680 /*
681 * UINCODEをアスキー文字列に変換
682 */
683 if(psrc[1] == STRING_DESCRIPTOR){ /* String Typeならバッファにセット */
684 int strlength = psrc[0]-2;
685 uint32_t i;
686 for(i = 0 ; i < length && i < strlength ; i += 2){
687 *buff++ = psrc[i+2];
688 }
689 *buff = 0;
690 }
691 }
692 return ercd;
693}
694
695/*
696 * USBのエナミュレートを実行する
697 * parameter1 pdevice: デバイスハンドラ
698 * return TUSBH_ERCODE
699 */
700static TUSBH_ERCODE
701tusbhEnumerate(TUSBH_Device_t *pdevice)
702{
703 TUSBH_ERCODE ercd = TUSBH_E_OK;
704
705 /*
706 * 8バイトで Device Descriptorを取得
707 */
708 if((ercd = tusbhGetDeviceDescriptor(pdevice, 8)) != TUSBH_E_OK)
709 return ercd;
710
711 /*
712 * bMaxPacketSizeでパイプを再オープン
713 */
714 pdevice->cntl_pipe_size = pdevice->DevDesc.bMaxPacketSize;
715 tusbhOpenPipe(pdevice, pdevice->cntl_pipe_in, 0x80, USB_EP_TYPE_CTRL,
716 pdevice->cntl_pipe_size);
717
718 tusbhOpenPipe(pdevice, pdevice->cntl_pipe_out, 0x00, USB_EP_TYPE_CTRL,
719 pdevice->cntl_pipe_size);
720
721 /*
722 * フルサイズで Device Descriptorを取得
723 */
724 if((ercd != tusbhGetDeviceDescriptor(pdevice, DEVICE_DESCRIPTOR_LENGTH)) != TUSBH_E_OK)
725 return ercd;
726
727 syslog_1(LOG_NOTICE, "VID: 0x%04x", pdevice->DevDesc.idVendor );
728 syslog_1(LOG_NOTICE, "PID: 0x%04x", pdevice->DevDesc.idProduct);
729
730 /*
731 * デバイスにデバイスアドレスをセット
732 */
733 if((ercd = USBH_SET_ADDRESS(pdevice, USBH_DEVICE_ADDRESS(pdevice))) != TUSBH_E_OK)
734 return ercd;
735
736 /*
737 * 設定アドレスでパイプを再オープン
738 */
739 tusbDelay(2);
740 pdevice->address = USBH_DEVICE_ADDRESS(pdevice);
741 syslog_1(LOG_NOTICE, "Address (#%d) assigned.", pdevice->address);
742
743 tusbhOpenPipe(pdevice, pdevice->cntl_pipe_in, 0x80, USB_EP_TYPE_CTRL,
744 pdevice->cntl_pipe_size);
745
746 tusbhOpenPipe(pdevice, pdevice->cntl_pipe_out, 0x00, USB_EP_TYPE_CTRL,
747 pdevice->cntl_pipe_size);
748
749 /*
750 * スタンダードサイズで Configuration descriptorを取得
751 */
752 if((ercd = tusbhGetConfigDescriptor(pdevice, CONFIGURATION_DESCRIPTOR_LENGTH)) != TUSBH_E_OK)
753 return ercd;
754
755 /*
756 * フルサイズでConfiguraion Descriptorを取得
757 */
758 if((ercd = tusbhGetConfigDescriptor(pdevice, pdevice->CfgDesc.wTotalLength)) != TUSBH_E_OK)
759 return ercd;
760
761 /*
762 * Manufacturer文字列を取得
763 */
764 if(pdevice->DevDesc.iManufacturer != 0){ /* Check that Manufacturer String is available */
765 if(tusbhGetStringDescriptor(pdevice, pdevice->DevDesc.iManufacturer,
766 pdevice->Data , 0xff) == TUSBH_E_OK){
767 strncpy(pdevice->Manufacturer, (const char *)pdevice->Data, TUSBH_STR_LENGTH);
768 /*
769 * Manufacturingを表示
770 */
771 syslog_1(LOG_NOTICE, "Manufacturer : %s", pdevice->Manufacturer);
772 }
773 }
774 else
775 syslog_0(LOG_NOTICE, "Manufacturer : N/A");
776
777 /*
778 * Product文字列を取得
779 */
780 if(pdevice->DevDesc.iProduct != 0){ /* Check that Product string is available */
781 if(tusbhGetStringDescriptor(pdevice, pdevice->DevDesc.iProduct,
782 pdevice->Data, 0xff) == TUSBH_E_OK){
783 strncpy(pdevice->Prodeuct, (const char *)pdevice->Data, TUSBH_STR_LENGTH);
784 /* User callback for Product string */
785 syslog_1(LOG_NOTICE, "Product : %s", pdevice->Prodeuct);
786 }
787 }
788 else
789 syslog_0(LOG_NOTICE, "Product : N/A");
790
791 /*
792 * シリアル番号取得
793 */
794 if(pdevice->DevDesc.iSerialNumber != 0){ /* Check that Serial number string is available */
795 if((ercd = tusbhGetStringDescriptor(pdevice, pdevice->DevDesc.iSerialNumber,
796 pdevice->Data, 0xff)) == TUSBH_E_OK){
797 strncpy(pdevice->Serial, (const char *)pdevice->Data, TUSBH_STR_LENGTH);
798 /* User callback for Serial number string */
799 syslog_1(LOG_NOTICE, "Serial Number : %s", pdevice->Serial);
800 }
801 }
802 else{
803 syslog_0(LOG_NOTICE, "Serial Number : N/A");
804 ercd = TUSBH_E_OK;
805 }
806 return ercd;
807}
808
809/*
810 * USBホストプロセスタスク
811 */
812void
813tusbhProcessTask(intptr_t exinf)
814{
815 TUSBH_Handle_t *phost = usbh_arg;
816 TUSBH_Device_t *pdevice;
817 TUSBH_Class_t *pnext;
818 TUSBH_ERCODE ercd = TUSBH_E_OK;
819 ER rercd;
820 uint8_t mes[4];
821 uint32_t no;
822
823 for(;;){
824 rercd = tusbRecvData(phost->process_event, mes, 0);
825 if(rercd == E_OK){
826 if((pdevice = tusbhFindDevice(phost, mes[1])) == NULL){
827 syslog_1(LOG_NOTICE, "USBH no device message(%d) !", mes[1]);
828 continue;
829 }
830 pdevice = tusbhFindDevice(phost, mes[1]);
831 switch (pdevice->dstate){
832 case DEVICE_ATTACHED:
833 syslog_2(LOG_NOTICE, "USBH Device Attached(%d) speed(%d) !", pdevice->idx, pdevice->speed);
834 if(phost->usrcallback != NULL)
835 phost->usrcallback(phost, pdevice, HOST_USER_CONNECTION);
836
837 /*
838 * 100ms待ちコントロール通信用PIPEをアサイン
839 */
840 tusbDelay(100);
841
842 pdevice->cntl_pipe_out = tusbhAllocPipe(phost, 0x00);
843 pdevice->cntl_pipe_in = tusbhAllocPipe(phost, 0x80);
844
845 /*
846 * IN/OUTのPIPEをオープン
847 */
848 tusbhOpenPipe(pdevice, pdevice->cntl_pipe_in, 0x80, USB_EP_TYPE_CTRL,
849 pdevice->cntl_pipe_size);
850
851 tusbhOpenPipe(pdevice, pdevice->cntl_pipe_out, 0x00, USB_EP_TYPE_CTRL,
852 pdevice->cntl_pipe_size);
853 pdevice->numUnit = 1;
854 pdevice->pre_connected = 0;
855
856 /*
857 * エナミュレーション実行
858 */
859 if((ercd = tusbhEnumerate(pdevice)) == TUSBH_E_OK){
860 syslog_1(LOG_NOTICE, "Enumeration done(%d) !", pdevice->idx);
861 pdevice->sel_interface = 0;
862 if(pdevice->DevDesc.bNumConfigurations != 1){
863 if(phost->usrcallback != NULL)
864 phost->usrcallback(phost, pdevice, HOST_USER_SELECT_CONFIGURATION);
865 }
866 else
867 syslog_1(LOG_NOTICE, "This device has only 1 configuration(%d) !", pdevice->idx);
868 if(USBH_SET_CONFIGURATION(pdevice, pdevice->CfgDesc.bConfigurationValue) == TUSBH_E_OK){
869 pdevice->dstate = DEVICE_CHECK_CLASS;
870 syslog_1(LOG_NOTICE, "Default configuration set(%d) !", pdevice->idx);
871 }
872 else if(ercd == TUSBH_E_ERR){
873 pdevice->dstate = DEVICE_DISCONNECTED;
874 syslog_1(LOG_ERROR, "Enumeration set configuraion error(%) !", pdevice->idx);
875 tusbSendData(phost->process_event, TUSBH_PORT_EVENT, pdevice->idx, 0, 0);
876 }
877 }
878 else{
879 pdevice->dstate = DEVICE_DISCONNECTED;
880 syslog_2(LOG_ERROR, "Enumeration sequence fail idx(%d) ercd(%d) !", pdevice->idx, ercd);
881 tusbSendData(phost->process_event, TUSBH_PORT_EVENT, pdevice->idx, 0, 0);
882 }
883 break;
884 case DEVICE_CHECK_CLASS:
885 pdevice->pClass = NULL;
886 for(no = 0, pnext = phost->pClass ; no < phost->numClass ; no++){
887 if(pnext->classCode == pdevice->ItfDesc[0].bInterfaceClass){
888 pdevice->pClass = pnext;
889 break;
890 }
891 pnext = pnext->pNext;
892 }
893 if(pdevice->pClass != NULL){
894 if((ercd = pdevice->pClass->Init(pdevice)) == TUSBH_E_OK){
895 syslog_2(LOG_NOTICE, "Class start[%s] (%d) !", pdevice->pClass->Name, pdevice->idx);
896 pdevice->dstate = DEVICE_CLASS;
897 pdevice->type = pdevice->pClass->classCode;
898 if(phost->usrcallback != NULL)
899 phost->usrcallback(phost, pdevice, HOST_USER_CLASS_SELECTED);
900 if(tusbActivateDevice(phost) == 1)
901 tusbTimerControl(1);
902 }
903 else{
904 pdevice->dstate = DEVICE_ABORT_STATE;
905 syslog_3(LOG_ERROR, "Class[%s] initial error(%d) (%d) !", pdevice->pClass->Name, ercd, pdevice->idx);
906 }
907 }
908 else{
909 pdevice->dstate = DEVICE_ABORT_STATE;
910 syslog_1(LOG_ERROR, "No registered class for this device(%d) !", pdevice->idx);
911 }
912 break;
913 case DEVICE_CLASS:
914 /*
915 * USB HOSTクラス処理
916 */
917 if(pdevice->pClass != NULL)
918 pdevice->pClass->Process(pdevice, mes);
919 break;
920 case DEVICE_DISCONNECTED:
921 /*
922 * USB HOSTクラスの終了処理
923 */
924 syslog_1(LOG_NOTICE, "USBH device disconnect(%d) !", pdevice->idx);
925 if(pdevice->pClass != NULL){
926 pdevice->pClass->DeInit(pdevice);
927 pdevice->pClass = NULL;
928 }
929 tusbhInitDevice(pdevice);
930 if(tusbActivateDevice(phost) == 0)
931 tusbTimerControl(0);
932 pdevice->dstate = DEVICE_IDLE;
933 break;
934
935 case DEVICE_IDLE:
936 case DEVICE_ABORT_STATE:
937 default :
938 break;
939 }
940 }
941 }
942}
943
944/*
945 * タイマハンドラ
946 */
947void
948tusbhCyclicHandler(intptr_t exinf)
949{
950 TUSBH_Handle_t *phost = usbh_arg;
951 TUSBH_Device_t *pdevice;
952 uint8_t i;
953
954 if(phost == NULL)
955 return;
956 pdevice = phost->pDevice;
957 for(i = 0 ; i < phost->numDevice && pdevice != NULL ; i++){
958 if(pdevice->pClass != NULL && pdevice->timecount > 0){
959 if(--pdevice->timecount == 0)
960 tusbiSendData(phost->process_event, TUSBH_TIME_EVENT, pdevice->idx, 0, pdevice->timeid);
961 }
962 pdevice = pdevice->pNext;
963 }
964}
965
966/*
967 * USBデバイスコネクト処理
968 */
969static void
970tusbhHandleConnect(TUSBH_Handle_t *phost, uint8_t hub, uint8_t port, uint8_t prm)
971{
972 TUSBH_Device_t *pdevice;
973 uint32_t no;
974
975 for(no = 0, pdevice = phost->pDevice ; no < phost->numDevice && pdevice != NULL ; no++){
976 if(pdevice->activate != 0 && pdevice->hub == hub && pdevice->port == port){
977 break;
978 }
979 pdevice = pdevice->pNext;
980 }
981 if(pdevice == NULL){
982 pdevice = tusbhAllocDevice(phost);
983 if(pdevice == NULL || pdevice->idx != no){
984 syslog_2(LOG_ERROR, "usbh device allocation error (%d)(%d) !", no, pdevice->idx);
985 return;
986 }
987 }
988 if(phost->numClass == 0)
989 syslog_0(LOG_ERROR, "No Regist Class !");
990 else if(pdevice != NULL){
991 if(pdevice->pre_connected == 0){
992 syslog_4(LOG_INFO, "connect pdevice[%08x] hub(%d) port(%d) speed(%d) !", pdevice, hub, port, prm);
993 pdevice->hub = hub;
994 pdevice->port = port;
995 pdevice->activate = 1;
996 pdevice->pre_connected = 1;
997
998 /*
999 * 接続後 CONNECT_WAIT_TIME ms待ち
1000 */
1001 tusbDelay(CONNECT_WAIT_TIME);
1002 if(hub == 0){
1003 tusbhHDResetPort(phost);
1004 tusbDelay(100);
1005 pdevice->speed = tusbhHDGetSpeed(phost);
1006 }
1007 else{
1008 pdevice->speed = prm;
1009 tusbDelay(200);
1010 }
1011 pdevice->is_connected = 1;
1012 if(pdevice->dstate == DEVICE_IDLE){
1013 pdevice->dstate = DEVICE_ATTACHED;
1014 tusbSendData(phost->process_event, TUSBH_PORT_EVENT, pdevice->idx, 0, 0);
1015 }
1016 }
1017 else if(pdevice->dstate == DEVICE_DISCONNECTED)
1018 tusbSendData(phost->process_event, TUSBH_PORT_EVENT, pdevice->idx, 0, 0);
1019 }
1020}
1021
1022/*
1023 * USBデバイスディスコネクト処理
1024 */
1025static void
1026tusbhHandleDisconnect(TUSBH_Handle_t *phost, uint8_t hub, uint8_t port, uint8_t prm)
1027{
1028 TUSBH_Device_t *pdevice = phost->pDevice;
1029 uint32_t no;
1030
1031 for(no = 0 ; no < phost->numDevice ; no++, pdevice = pdevice->pNext){
1032 if(pdevice == NULL)
1033 return;
1034 if(pdevice->activate != 0 && pdevice->hub == hub && pdevice->port == port)
1035 break;
1036 }
1037 if(no >= phost->numDevice)
1038 return;
1039 if(pdevice->is_connected == 0)
1040 return;
1041
1042 /*
1043 * Hostペリフェラル停止
1044 */
1045 if(hub == 0)
1046 tusbhHDStop(phost);
1047
1048 /*
1049 * コントロール通信用PIPEを解放
1050 */
1051 tusbhClosePipe(pdevice, pdevice->cntl_pipe_in);
1052 tusbFreePipe(phost, pdevice->cntl_pipe_in);
1053 tusbhClosePipe(pdevice, pdevice->cntl_pipe_out);
1054 tusbFreePipe(phost, pdevice->cntl_pipe_out);
1055
1056 pdevice->is_connected = 0;
1057 pdevice->pre_connected = 0;
1058
1059 /*
1060 * ユーザーへ通知
1061 */
1062 if(phost->usrcallback != NULL)
1063 phost->usrcallback(phost, pdevice, HOST_USER_DISCONNECTION);
1064 syslog_4(LOG_NOTICE, "USB Device disconnected [%02x][%02x][%02x] device(%d) !", hub, port, prm, pdevice->idx);
1065
1066 /*
1067 * Hostペリフェラル再開
1068 */
1069 if(hub == 0)
1070 tusbhHDStart(phost);
1071
1072 pdevice->dstate = DEVICE_DISCONNECTED;
1073 tusbSendData(phost->process_event, TUSBH_PORT_EVENT, pdevice->idx, 0, 0);
1074}
1075
1076/*
1077 * USBホストイベントタスク
1078 */
1079void
1080tusbhEventTask(intptr_t exinf)
1081{
1082 uint8_t mes[4];
1083 ER ercd;
1084
1085 for(;;){
1086 ercd = tusbRecvData(usbh_arg->connect_event, mes, 0);
1087
1088 if(ercd == E_OK){
1089 syslog_4(LOG_INFO, "usbh_task evt(%d) [%02x][%02x][%02x] !", mes[0], mes[1], mes[2], mes[3]);
1090 if(mes[0] == TUSBH_CONNECT_EVENT)
1091 tusbhHandleConnect(usbh_arg, mes[1], mes[2], mes[3]);
1092 else if(mes[0] == TUSBH_DISCONNECT_EVENT){
1093 dly_tsk(200);
1094 tusbhHandleDisconnect(usbh_arg, mes[1], mes[2], mes[3]);
1095 }
1096 else if(mes[0] == TUSBH_IDCHANGE_EVENT){
1097 dly_tsk(200);
1098 tusbhHDStart(usbh_arg);
1099 }
1100 }
1101 }
1102}
1103
1104
Note: See TracBrowser for help on using the repository browser.