source: azure_iot_hub_f767zi/trunk/asp_baseplatform/usb/host/HID/tusbh_hid.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: 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 HID CLASS部
40 */
41
42#include "tusbh_hid.h"
43
44
45#define HID_SETIDLE(d, dur, rep) tusbhControlRequest((d), NULL, HID_SET_TYPE, USB_HID_SET_IDLE, ((dur << 8) | (rep)), 0, 0)
46#define HID_SETPROTOCOL(d, p) tusbhControlRequest((d), NULL, HID_SET_TYPE, USB_HID_SET_PROTOCOL, (((p) != 0) ? 0 : 1), 0, 0)
47#define HID_GETREPORT(d, t, i, b, l) tusbhControlRequest((d), (b), HID_GET_TYPE, USB_HID_GET_REPORT, ((t << 8 ) | i), 0, (l))
48#define HID_SETREPORT(d, t, i, b, l) tusbhControlRequest((d), (b), HID_SET_TYPE, USB_HID_SET_REPORT, ((t << 8 ) | i), 0, (l))
49
50static TUSBH_ERCODE tusbhHIDInit(TUSBH_Device_t *pdevice);
51static TUSBH_ERCODE tusbhHIDDeInit(TUSBH_Device_t *pdevice);
52static TUSBH_ERCODE tusbdHIDProcess(TUSBH_Device_t *pdevice, uint8_t *mes);
53
54TUSBH_Class_t HID_Class = {
55 NULL,
56 "HID",
57 HID_CLASS,
58 tusbhHIDInit,
59 tusbhHIDDeInit,
60 tusbdHIDProcess,
61 NULL
62};
63
64/*
65 * HIDクラスセットアップ関数
66 */
67void tusbhLinkHID(TUSBH_Handle_t *phost)
68{
69 tusbhLinkClass(phost, &HID_Class);
70}
71
72/*
73 * HIDクラス初期設定
74 * parameter1 pdevice: デバイスハンドラ
75 * return TUSBH_ERCODE
76 */
77static TUSBH_ERCODE
78tusbhHIDInit(TUSBH_Device_t *pdevice)
79{
80 TUSBH_Handle_t *phost = pdevice->pHost;
81 uint8_t max_ep;
82 uint8_t interface;
83 TUSBH_ERCODE status = TUSBH_E_ERR;
84 HID_Handle_t *hhid;
85
86 interface = tusbhFindInterface(pdevice, pdevice->pClass->classCode, HID_BOOT_CODE, 0xFF);
87
88 if(interface == NO_INTERFACE){
89 syslog_1(LOG_ERROR, "[HID] Cannot Find the interface for %s class !", pdevice->pClass->Name);
90 return TUSBH_E_ERR;
91 }
92
93 tusbhSelectInterface(pdevice, interface);
94 pdevice->pData = tusbmalloc(sizeof(HID_Handle_t));
95 hhid = (HID_Handle_t *)pdevice->pData;
96 memset(hhid, 0, sizeof(HID_Handle_t));
97 hhid->state = THID_ERROR;
98
99 /*
100 * デバイスの検索
101 */
102 if(pdevice->ItfDesc[pdevice->sel_interface].bInterfaceProtocol == HID_KEYBRD_BOOT_CODE){
103 syslog_0(LOG_NOTICE, "[HID] found KeyBoard device !");
104 hhid->type = HID_KEYBOARD_TYPE;
105 }
106 else if(pdevice->ItfDesc[pdevice->sel_interface].bInterfaceProtocol == HID_MOUSE_BOOT_CODE){
107 syslog_0(LOG_NOTICE, "[HID] found Mouse device !");
108 hhid->type = HID_MOUSE_TYPE;
109 }
110 else{
111 syslog_0(LOG_ERROR, "[HID] no device !");
112 return TUSBH_E_ERR;
113 }
114
115 hhid->ep_addr = pdevice->EpDesc[pdevice->sel_interface][0].bEndpointAddress;
116 hhid->length = pdevice->EpDesc[pdevice->sel_interface][0].wMaxPacketSize;
117 hhid->poll = pdevice->EpDesc[pdevice->sel_interface][0].bInterval ;
118
119 if(hhid->poll < HID_MIN_POLL)
120 hhid->poll = HID_MIN_POLL;
121
122 max_ep = pdevice->ItfDesc[pdevice->sel_interface].bNumEndpoints;
123 if(max_ep == 0 || (pdevice->EpDesc[pdevice->sel_interface][0].bEndpointAddress & 0x80) == 0)
124 return TUSBH_E_ERR;
125
126#if 1 /* ROI DEBUG */
127 syslog_3(LOG_NOTICE, "## max_ep(%d) length(%d) poll(%d) ##", max_ep, hhid->length, hhid->poll);
128#endif /* ROI DEBUG */
129 if(hhid->length > HID_MAX_REPORT_LENGTH)
130 hhid->length = HID_MAX_REPORT_LENGTH;
131
132 /*
133 * インターラプト インエンドポイント オープン
134 */
135 hhid->InPipe = tusbhAllocPipe(phost, hhid->ep_addr);
136 tusbhOpenPipe(pdevice, hhid->InPipe, hhid->ep_addr, USB_EP_TYPE_INTR, hhid->length);
137 tusbhHDSetToggle(phost, hhid->InPipe, 0);
138
139 /*
140 * HID DESCRIPTOR取得
141 */
142 if(tusbhGetDescriptor(pdevice, (USB_RECIPIENT_INTERFACE | USB_REQUEST_TYPE_STANDARD),
143 ((HID_DESCRIPTOR << 8) & 0xFF00), pdevice->Data, HID_DESCRIPTOR_LENGTH) != TUSBH_E_OK)
144 return TUSBH_E_ERR;
145 hhid->ReportDescLength = (pdevice->Data[7] & 0xff) | (pdevice->Data[8] << 8);
146 syslog_1(LOG_NOTICE, "## hhid->DescLength(%d) ##", hhid->ReportDescLength);
147 if(hhid->ReportDescLength > 64)
148 hhid->ReportDescLength = 64;
149
150 /*
151 * HID REPORT DESCRIPTOR取得
152 */
153 if(tusbhGetDescriptor(pdevice, (USB_RECIPIENT_INTERFACE | USB_REQUEST_TYPE_STANDARD),
154 ((HID_REPORT_DESCRIPTOR << 8) & 0xFF00), pdevice->Data, hhid->ReportDescLength) != TUSBH_E_OK)
155 return TUSBH_E_ERR;
156 tusbmemcpy(hhid->ReportDesc, pdevice->Data, hhid->ReportDescLength);
157 syslog_1(LOG_NOTICE, "## hhid->ReportDesc[%08x] ##", hhid->ReportDesc);
158
159 /*
160 * IDEL設定
161 */
162 status = HID_SETIDLE(pdevice, 0, 0);
163 if(status != TUSBH_E_OK && status != TUSBH_E_NOSPT)
164 return status;
165
166 /*
167 * PROTOCOL #0 設定
168 */
169 if((status = HID_SETPROTOCOL(pdevice, 0)) != TUSBH_E_OK)
170 return status;
171
172 /* タイマースタート */
173 hhid->state = THID_INIT;
174 pdevice->timeid = pdevice->timecount = hhid->poll;
175 return TUSBH_E_OK;
176}
177
178/*
179 * HUBクラス終了設定
180 * parameter1 pdevice: デバイスハンドラ
181 * return TUSBH_ERCODE
182 */
183static TUSBH_ERCODE
184tusbhHIDDeInit(TUSBH_Device_t *pdevice)
185{
186 TUSBH_Handle_t *phost = pdevice->pHost;
187 HID_Handle_t *hhid;
188
189 hhid = (HID_Handle_t *)pdevice->pData;
190 if(hhid->InPipe != 0x00){
191 tusbhClosePipe(pdevice, hhid->InPipe);
192 tusbFreePipe(phost, hhid->InPipe);
193 hhid->InPipe = 0;
194 }
195
196 if(pdevice->pData != NULL){
197 tusbfree(pdevice->pData);
198 pdevice->pData = NULL;
199 }
200 return TUSBH_E_OK;
201}
202
203
204/*
205 * HIDクラスプロセス実行
206 * parameter1 pdevice: デバイスハンドラ
207 * parameter2 mes: 通信メッセージへのポインタ
208 * return TUSBH_ERCODE
209 */
210static TUSBH_ERCODE
211tusbdHIDProcess(TUSBH_Device_t *pdevice, uint8_t *mes)
212{
213 TUSBH_ERCODE status = TUSBH_E_OK, status2;
214 HID_Handle_t *hhid = (HID_Handle_t *)pdevice->pData;
215 TUSBH_URBState_t URB_Status = mes[3];
216 TUSBH_Handle_t *phost = pdevice->pHost;
217 void (*func)(TUSBH_Device_t *, uint8_t, uint8_t *) = pdevice->pClass->subfunc;
218
219 switch (hhid->state){
220 case THID_INIT:
221 if(phost->usrcallback != NULL)
222 phost->usrcallback(phost, pdevice, HOST_USER_CLASS_ACTIVE);
223 case THID_IDLE:
224 hhid->ReportType = 0x01;
225 hhid->ReportId = 0;
226 HID_GETREPORT(pdevice, hhid->ReportType, hhid->ReportId, hhid->buffer, hhid->length);
227 hhid->state = THID_GETREPORT_WAIT;
228 break;
229 case THID_GETREPORT_WAIT:
230 if((status2 = tusbhControlWait(pdevice, mes)) == TUSBH_E_OK){
231 hhid->ReportLength = hhid->length;
232 tusbmemcpy(hhid->Report, hhid->buffer, hhid->ReportLength);
233 if(func != NULL)
234 func(pdevice, 0, hhid->Report);
235 syslog_2(LOG_NOTICE, "## THID_GETREPORT_WAIT hhid->Report[%08x] (%d) ##", hhid->Report, hhid->ReportLength);
236 hhid->state = THID_GET_DATA;
237 pdevice->timeid = hhid->poll;
238 pdevice->timecount = hhid->poll;
239 }
240 else if(status2 == TUSBH_E_NOSPT){
241 if(func != NULL)
242 func(pdevice, 0, 0);
243 hhid->state = THID_GET_DATA;
244 pdevice->timeid = hhid->poll;
245 pdevice->timecount = hhid->poll;
246 }
247 else if(status2 != TUSBH_E_BUSY && status2 != TUSBH_E_BUSY_URB){
248 syslog_1(LOG_NOTICE, "## tusbdHIDProcess ERROR status(%d) ##", status2);
249 hhid->state = THID_ERROR;
250 }
251 break;
252 case THID_SETREPORT:
253 tusbmemcpy(hhid->buffer, hhid->Report, hhid->ReportLength);
254 HID_SETREPORT(pdevice, hhid->ReportType, hhid->ReportId, hhid->buffer, hhid->ReportLength);
255 hhid->state = THID_SETREPORT_WAIT;
256 break;
257 case THID_SETREPORT_WAIT:
258 if((status2 = tusbhControlWait(pdevice, mes)) == TUSBH_E_OK){
259 syslog_2(LOG_NOTICE, "## THID_SETREPORT_WAIT(1) hhid->Report[%08x] (%d) ##", hhid->Report, hhid->ReportLength);
260 hhid->state = THID_GET_DATA;
261 pdevice->timeid = hhid->poll;
262 pdevice->timecount = hhid->poll;
263 }
264 else if(status2 == TUSBH_E_NOSPT){
265 syslog_2(LOG_NOTICE, "## THID_SETREPORT_WAIT(2) hhid->Report[%08x] (%d) ##", hhid->Report, hhid->ReportLength);
266 hhid->state = THID_GET_DATA;
267 pdevice->timeid = hhid->poll;
268 pdevice->timecount = hhid->poll;
269 }
270 else if(status2 != TUSBH_E_BUSY && status2 != TUSBH_E_BUSY_URB){
271 syslog_1(LOG_NOTICE, "## tusbdHIDProcess ERROR status(%d) ##", status2);
272 hhid->state = THID_ERROR;
273 }
274 break;
275 case THID_GET_DATA:
276 if(pdevice->is_connected == 0)
277 break;
278 if(hhid->ReqReport == 0xFF){
279 hhid->state = THID_SETREPORT;
280 tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
281 break;
282 }
283 tusbhInterruptRead(pdevice, hhid->buffer, hhid->length, hhid->InPipe);
284 hhid->state = THID_POLL;
285 hhid->DataReady = 0;
286 break;
287 case THID_POLL:
288 if(mes[0] != TUSBH_URB_EVENT)
289 break;
290 if(URB_Status == TUSBH_URB_DONE){
291 if(hhid->DataReady == 0){
292 hhid->DataReady = 1;
293 if(func != NULL)
294 func(pdevice, hhid->length, hhid->buffer);
295 pdevice->timeid = hhid->poll;
296 pdevice->timecount = hhid->poll;
297 hhid->state = THID_GET_DATA;
298 }
299 }
300 else if(URB_Status == TUSBH_URB_STALL){
301 /*
302 * STALLならCLEAR FEATURE実行
303 */
304 if(tusbhClearFeature(pdevice, hhid->ep_addr) == TUSBH_E_OK){
305 /* Change state to issue next IN token */
306 hhid->state =THID_CLEARFEATURE_WAIT;
307 }
308 }
309 else{
310 pdevice->timeid = hhid->poll;
311 pdevice->timecount = hhid->poll;
312 hhid->state = THID_GET_DATA;
313 }
314 break;
315 case THID_CLEARFEATURE_WAIT:
316 if((status2 = tusbhControlWait(pdevice, mes)) == TUSBH_E_OK){
317 hhid->state = THID_GET_DATA;
318 pdevice->timeid = hhid->poll;
319 pdevice->timecount = hhid->poll;
320 }
321 else if(status2 == TUSBH_E_NOSPT){
322 hhid->state = THID_GET_DATA;
323 pdevice->timeid = hhid->poll;
324 pdevice->timecount = hhid->poll;
325 }
326 else if(status2 != TUSBH_E_BUSY && status2 != TUSBH_E_BUSY_URB){
327 syslog_1(LOG_ERROR, "tusbdHIDProcess ERROR status(%d) !", status2);
328 hhid->state = THID_ERROR;
329 }
330 break;
331
332 default:
333 break;
334 }
335 return status;
336}
337
338/*
339 * HIDデバイスリポート設定
340 * parameter1 hhid: HIDハンドラ
341 * parameter2 type: report type
342 * parameter3 id: report id
343 * parameter4 pbuf: report data
344 * parameter5 len: report data length
345 * return TUSBH_ERCODE
346 */
347TUSBH_ERCODE
348tubhHidSetReport(HID_Handle_t *hhid, uint8_t type, uint8_t id, uint8_t* pbuf, uint8_t len)
349{
350 hhid->ReportType = type;
351 hhid->ReportId = id;
352 hhid->ReportLength = len;
353 tusbmemcpy(hhid->Report, pbuf, hhid->ReportLength);
354 hhid->ReqReport = 0xFF;
355 while(hhid->ReqReport == 0xFF){
356 tusbSleep(10);
357 }
358 return (TUSBH_ERCODE)hhid->ReqReport;
359}
360
361/*
362 * HIDデバイスタイプ取得
363 * parameter1 hhid: HIDハンドラ
364 * return poll デバイスタイプ
365 */
366uint8_t
367tusbhHidGetType(TUSBH_Device_t *pdevice)
368{
369 HID_Handle_t *hhid = (HID_Handle_t *)pdevice->pData;
370
371 if(hhid == NULL)
372 return HID_UNKNOWN_TYPE;
373 else
374 return hhid->type;
375}
376
377
378/*
379 * HIDポーリングインターバル時間取得
380 * parameter1 hhid: HIDハンドラ
381 * return poll インターバル時間(ms)
382 */
383uint8_t
384tusbhHidGetPollInterval(TUSBH_Device_t *pdevice)
385{
386 HID_Handle_t *hhid = (HID_Handle_t *)pdevice->pData;
387
388 if(hhid == NULL)
389 return 0;
390 else
391 return hhid->poll;
392}
393
394/*
395 * HID コールバック関数設定
396 */
397void
398tusbhSetHidCallBack(TUSBH_Handle_t *phost, void (*func)(TUSBH_Device_t *pdevice, uint8_t, uint8_t *))
399{
400 HID_Class.subfunc = func;
401}
402
Note: See TracBrowser for help on using the repository browser.