1 /*
2 ********************************************************************************
3 *                                USB Hid Driver
4 *
5 *                (c) Copyright 2006-2010, All winners Co,Ld.
6 *                        All Right Reserved
7 *
8 * FileName      :  HidTransport.c
9 *
10 * Author        :  Javen
11 *
12 * Date          :  2010/06/02
13 *
14 * Description   :  Hid 传输
15 *
16 * Others        :  NULL
17 *
18 * History:
19 *       <time>          <author>     <version >     <desc>
20 *      2010.06.02       Javen           1.0         build this file
21 *
22 ********************************************************************************
23 */
24 
25 //#include  "usb_host_config.h"
26 //#include  "usb_host_base_types.h"
27 #include  "usb_os_platform.h"
28 #include  "error.h"
29 
30 #include  "usb_host_common.h"
31 #include  "urb.h"
32 #include  "usb_gen_hub.h"
33 
34 #include  "HidSpec.h"
35 #include  "Hid_i.h"
36 #include  "HidProtocol.h"
37 #include  "HidTransport.h"
38 
39 /*
40 *******************************************************************************
41 *                     HidTransportDone
42 *
43 * Description:
44 *
45 *
46 * Parameters:
47 *
48 *
49 * Return value:
50 *
51 *
52 * note:
53 *    无
54 *
55 *******************************************************************************
56 */
HidTransportDone(struct urb * urb)57 static void HidTransportDone(struct urb *urb)
58 {
59     hal_sem_t urb_done = (hal_sem_t)urb->context;
60 
61     if(urb_done){
62         hal_sem_post(urb_done);
63     }else{
64         hal_log_err("ERR: mscUrbCallBack: urb_done == NULL\n");
65     }
66 }
67 
68 /*
69 *******************************************************************************
70 *                     HidUsbTransport
71 *
72 * Description:
73 *
74 *
75 * Parameters:
76 *
77 *
78 * Return value:
79 *
80 *
81 * note:
82 *    无
83 *
84 *******************************************************************************
85 */
HidUsbTransport(HidDev_t * HidDev)86 static int HidUsbTransport(HidDev_t *HidDev)
87 {
88     int ret = 0;
89     unsigned char err = 0;
90 
91     if(HidDev == NULL){
92         hal_log_err("ERR: HidUsbTransport: input error\n");
93         return USB_ERR_BAD_ARGUMENTS;
94     }
95 
96     if(HidDev->State != HID_DEV_ONLINE){
97         hal_log_err("ERR: mscUSBTransport: Can't transport for device is not online\n");
98         return USB_ERR_BAD_ARGUMENTS;
99     }
100 
101     /* fill URB */
102     HidDev->CurrentUrb->context       = (void *)HidDev->UrbWait;
103     HidDev->CurrentUrb->actual_length = 0;
104     HidDev->CurrentUrb->error_count   = 0;
105     HidDev->CurrentUrb->status        = 0;
106     HidDev->CurrentUrb->transfer_dma  = 0;
107     HidDev->CurrentUrb->setup_dma     = 0;
108 
109     /* set HidDev busy */
110     HidDev->busy = 1;
111 
112     /* submit urb */
113     ret = usb_submit_urb(HidDev->CurrentUrb, 0);
114     if(ret == 0){
115         /* nothing to do */
116     }else if(ret == -ENODEV){
117         hal_log_err("ERR: device is not present, CurrentUrb = %d\n", HidDev->CurrentUrb);
118         HidDev->busy = 0;
119 
120         return USB_ERR_IO_DEVICE_OFFLINE;
121     }else{
122         hal_log_err("ERR: submit urb failed. ret = %d, CurrentUrb = %d\n", ret, HidDev->CurrentUrb);
123         HidDev->busy = 0;
124 
125         return USB_ERR_COMMAND_SEND_FAILED;
126     }
127 
128     /* wait urb done */
129 //  USB_OS_SemPend(HidDev->UrbWait, 0, &err);
130     hal_sem_wait(HidDev->UrbWait);
131 
132     /* urb is done, then set mscDev free */
133     HidDev->busy = 0;
134 
135     return USB_ERR_SUCCESS;
136 }
137 
138 /*
139 *******************************************************************************
140 *                     HidSoftReset
141 *
142 * Description:
143 *
144 *
145 * Parameters:
146 *
147 *
148 * Return value:
149 *
150 *
151 * note:
152 *    无
153 *
154 *******************************************************************************
155 */
HidSoftReset(HidDev_t * HidDev)156 int HidSoftReset(HidDev_t *HidDev)
157 {
158     if(HidDev == NULL){
159         hal_log_err("ERR: HidSoftReset: input error\n");
160         return USB_ERR_BAD_ARGUMENTS;
161     }
162 
163     /* device online? */
164     if(HidDev->State == HID_DEV_OFFLINE){
165         hal_log_err("ERR: HidPortReset: device is offline\n");
166         return USB_ERR_IO_DEVICE_OFFLINE;
167     }
168 
169     return HidSetIlde(HidDev, HidDev->InterfaceNo, 0, 0);
170 }
171 
172 /*
173 *******************************************************************************
174 *                     HidPortReset
175 *
176 * Description:
177 *    reset 设备
178 *
179 * Parameters:
180 *    mscDev  :  input. 目标设备
181 *
182 * Return value:
183 *    返回成功或者失败
184 *
185 * note:
186 *
187 *
188 *******************************************************************************
189 */
HidPortReset(HidDev_t * HidDev)190 static int HidPortReset(HidDev_t *HidDev)
191 {
192     int ret = 0;
193 
194     if(HidDev == NULL){
195         hal_log_err("ERR: HidPortReset: input error, mscDev = %x\n", HidDev);
196         return USB_ERR_BAD_ARGUMENTS;
197     }
198 
199     /* device online? */
200     if(HidDev->State == HID_DEV_OFFLINE){
201         hal_log_err("ERR: HidPortReset: device is offline\n");
202         return USB_ERR_IO_DEVICE_OFFLINE;
203     }
204 
205     /* reset a multi-interface device must be wariness */
206     if(HidDev->pusb_dev->actconfig->desc.bNumInterfaces != 1){
207         hal_log_err("ERR: Refusing to reset a multi-interface device\n");
208         return USB_ERR_IO_DEVICE_BUSY;
209     }
210 
211     /* reset device */
212     ret = usb_reset_device(HidDev->pusb_dev);
213     if(ret != 0){
214         hal_log_err("ERR: reset device failed\n");
215         return USB_ERR_RESET_POERT_FAILED;
216     }
217 
218     return USB_ERR_SUCCESS;
219 }
220 
221 /*
222 *******************************************************************************
223 *                     HidResetRecovery
224 *
225 * Description:
226 *
227 *
228 * Parameters:
229 *
230 *
231 * Return value:
232 *
233 *
234 * note:
235 *    无
236 *
237 *******************************************************************************
238 */
HidResetRecovery(HidDev_t * HidDev)239 int HidResetRecovery(HidDev_t *HidDev)
240 {
241     int ret = 0;
242 
243     ret = HidPortReset(HidDev);
244     if(ret != USB_ERR_SUCCESS){
245         hal_log_err("ERR: HidPortReset failed\n");
246         return USB_ERR_RESET_POERT_FAILED;
247     }
248 
249     ret = HidSoftReset(HidDev);
250     if(ret != USB_ERR_SUCCESS){
251         hal_log_err("ERR: HidSoftReset failed\n");
252         return USB_ERR_RESET_POERT_FAILED;
253     }
254 
255     return USB_ERR_SUCCESS;
256 }
257 
258 
259 /*
260 *******************************************************************************
261 *                     HidTransport
262 *
263 * Description:
264 *
265 *
266 * Parameters:
267 *
268 *
269 * Return value:
270 *
271 *
272 * note:
273 *    无
274 *
275 *******************************************************************************
276 */
277 #if 0 /* reset 多次 */
278 int HidTransport(HidDev_t *HidDev, HidRequest_t *HidReq)
279 {
280     int ret = 0;
281     __u32 retries = 3;
282 
283     /* fill urb */
284     usb_fill_int_urb( HidDev->CurrentUrb,
285                       HidDev->pusb_dev,
286                       HidDev->IntIn,
287                       HidReq->buffer,
288                       HidReq->DataTransferLength,
289                       HidTransportDone,
290                       NULL,
291                       HidDev->EpInterval);
292 
293 HidRetry:
294     /* summit urb */
295     ret = HidUsbTransport(HidDev);
296     if(ret != USB_ERR_SUCCESS){
297         hal_log_err("ERR: HidUsbTransport failed\n");
298         return USB_HID_TRANSPORT_PIPE_HALT;
299     }
300 
301     if(HidDev->CurrentUrb->status == -ESHUTDOWN){
302         hal_log_err("ERR: device is shut down\n");
303         return USB_HID_TRANSPORT_CANCEL_CMD;
304     }
305 
306     if(HidDev->CurrentUrb->status != 0 && retries--){
307         hal_log_err("ERR: HidTransport failed(%d), need retry %d\n",
308                     HidDev->CurrentUrb->status, retries);
309         ret = HidDev->ResetRecovery(HidDev);
310         if(ret != USB_ERR_SUCCESS){
311             hal_log_err("ERR: HidResetRecovery failed\n");
312             return USB_HID_TRANSPORT_DEVICE_DISCONNECT;
313         }
314 
315         goto HidRetry;
316     }
317 
318     /* retry的最后一次成功,不算其中 */
319     if(retries == 0 && HidDev->CurrentUrb->status != 0){
320         hal_log_err("ERR: HidTransport failed\n");
321         return USB_HID_TRANSPORT_DEVICE_DISCONNECT;
322     }
323 
324     return USB_HID_TRANSPORT_SUCCESS;
325 }
326 #else  /* 不reset */
HidTransport(HidDev_t * HidDev,HidRequest_t * HidReq)327 int HidTransport(HidDev_t *HidDev, HidRequest_t *HidReq)
328 {
329     int ret = 0;
330 
331     /* fill urb */
332     usb_fill_int_urb( HidDev->CurrentUrb,
333                       HidDev->pusb_dev,
334                       HidDev->IntIn,
335                       HidReq->buffer,
336                       HidReq->DataTransferLength,
337                       HidTransportDone,
338                       NULL,
339                       HidDev->EpInterval);
340 
341     /* summit urb */
342     ret = HidUsbTransport(HidDev);
343     if(ret == USB_ERR_SUCCESS){
344         /* nothing to do */
345     }else if(ret == USB_ERR_IO_DEVICE_OFFLINE){
346         hal_log_err("ERR: deivce is offline\n");
347         return USB_HID_TRANSPORT_DEVICE_DISCONNECT;
348     }else{
349         hal_log_err("ERR: HidUsbTransport failed, ret = %d\n", ret);
350         return USB_HID_TRANSPORT_PIPE_HALT;
351     }
352 
353     /* check urb status */
354     if(HidDev->CurrentUrb->status != 0){
355         hal_log_err("ERR: HidTransport failed(%d)\n", HidDev->CurrentUrb->status);
356 
357         /* driver取消了本次传输 */
358         if(HidDev->CurrentUrb->status == -ESHUTDOWN){
359             hal_log_err("ERR: HidTransport: device is shut down\n");
360             return USB_HID_TRANSPORT_CANCEL_CMD;
361         }
362 
363         if(HidDev->State == HID_DEV_OFFLINE){
364             hal_log_err("ERR: HidTransport: device is offline\n");
365             return USB_HID_TRANSPORT_DEVICE_DISCONNECT;
366         }
367 
368 /*
369         ret = HidDev->ResetRecovery(HidDev);
370         if(ret != USB_ERR_SUCCESS){
371             hal_log_err("ERR: HidResetRecovery failed\n");
372             return USB_HID_TRANSPORT_DEVICE_DISCONNECT;
373         }
374 */
375     }
376 
377     return USB_HID_TRANSPORT_SUCCESS;
378 }
379 #endif
380 
381 /*
382 *******************************************************************************
383 *                     HidStopTransport
384 *
385 * Description:
386 *
387 *
388 * Parameters:
389 *
390 *
391 * Return value:
392 *
393 *
394 * note:
395 *    无
396 *
397 *******************************************************************************
398 */
HidStopTransport(HidDev_t * HidDev)399 int HidStopTransport(HidDev_t *HidDev)
400 {
401     if(HidDev == NULL){
402         hal_log_err("ERR: HidStopTransport: input error, HidDev = %x\n", HidDev);
403         return USB_ERR_BAD_ARGUMENTS;
404     }
405 
406     if(HidDev->busy){
407         usb_unlink_urb(HidDev->CurrentUrb);
408         HidDev->CurrentUrb->status = -ESHUTDOWN;
409     }
410 
411     return USB_ERR_SUCCESS;
412 }
413 
414 
415