@@ -59,6 +59,129 @@ usb_dev_err_convert(int err)
59
59
return USB_ERR_IOERROR ;
60
60
}
61
61
62
+ static inline struct usb_dev_ep *
63
+ usb_dev_get_ep (struct usb_dev * udev , int pid , int ep )
64
+ {
65
+ assert (udev );
66
+
67
+ if (ep < 0 || ep >= USB_NUM_ENDPOINT ) {
68
+ UPRINTF (LWRN , "invalid ep %d\r\n" , ep );
69
+ return NULL ;
70
+ }
71
+
72
+ if (ep == 0 )
73
+ return & udev -> epc ;
74
+
75
+ if (pid == TOKEN_IN )
76
+ return udev -> epi + ep - 1 ;
77
+ else
78
+ return udev -> epo + ep - 1 ;
79
+ }
80
+
81
+ static inline void
82
+ usb_dev_set_ep_type (struct usb_dev * udev , int pid , int epnum ,
83
+ uint8_t type )
84
+ {
85
+ struct usb_dev_ep * ep ;
86
+
87
+ ep = usb_dev_get_ep (udev , pid , epnum );
88
+ if (ep )
89
+ ep -> type = type ;
90
+ }
91
+
92
+ static inline uint8_t
93
+ usb_dev_get_ep_type (struct usb_dev * udev , int pid , int epnum )
94
+ {
95
+ struct usb_dev_ep * ep ;
96
+
97
+ ep = usb_dev_get_ep (udev , pid , epnum );
98
+ if (!ep )
99
+ return USB_EP_ERR_TYPE ;
100
+ else
101
+ return ep -> type ;
102
+ }
103
+
104
+ static void
105
+ usb_dev_reset_ep (struct usb_dev * udev )
106
+ {
107
+ int ep ;
108
+
109
+ udev -> epc .type = USB_ENDPOINT_CONTROL ;
110
+ for (ep = 0 ; ep < USB_NUM_ENDPOINT ; ep ++ ) {
111
+ udev -> epi [ep ].pid = TOKEN_IN ;
112
+ udev -> epo [ep ].pid = TOKEN_OUT ;
113
+ udev -> epi [ep ].type = USB_ENDPOINT_INVALID ;
114
+ udev -> epo [ep ].type = USB_ENDPOINT_INVALID ;
115
+ }
116
+ }
117
+
118
+ static void
119
+ usb_dev_update_ep (struct usb_dev * udev )
120
+ {
121
+ struct libusb_config_descriptor * cfg ;
122
+ const struct libusb_interface_descriptor * _if ;
123
+ const struct libusb_endpoint_descriptor * desc ;
124
+ int i , j ;
125
+
126
+ assert (udev );
127
+ if (libusb_get_active_config_descriptor (udev -> ldev , & cfg ))
128
+ return ;
129
+
130
+ for (i = 0 ; i < cfg -> bNumInterfaces ; i ++ ) {
131
+ _if = & cfg -> interface [i ].altsetting [udev -> alts [i ]];
132
+
133
+ for (j = 0 ; j < _if -> bNumEndpoints ; j ++ ) {
134
+ desc = & _if -> endpoint [j ];
135
+ usb_dev_set_ep_type (udev ,
136
+ USB_EP_PID (desc ),
137
+ USB_EP_NR (desc ),
138
+ USB_EP_TYPE (desc ));
139
+ }
140
+ }
141
+ libusb_free_config_descriptor (cfg );
142
+ }
143
+
144
+ static int
145
+ usb_dev_native_toggle_if (struct usb_dev * udev , int claim )
146
+ {
147
+ struct libusb_config_descriptor * config ;
148
+ uint8_t b , p , c , i ;
149
+ int rc = 0 , r ;
150
+
151
+ assert (udev );
152
+ assert (udev -> handle );
153
+ assert (udev -> ldev );
154
+ assert (claim == 1 || claim == 0 );
155
+
156
+ b = udev -> bus ;
157
+ p = udev -> port ;
158
+
159
+ r = libusb_get_active_config_descriptor (udev -> ldev , & config );
160
+ if (r ) {
161
+ UPRINTF (LWRN , "%d-%d: can't get config\r\n" , b , p );
162
+ return -1 ;
163
+ }
164
+
165
+ c = config -> bConfigurationValue ;
166
+ for (i = 0 ; i < config -> bNumInterfaces ; i ++ ) {
167
+ if (claim == 1 )
168
+ r = libusb_claim_interface (udev -> handle , i );
169
+ else
170
+ r = libusb_release_interface (udev -> handle , i );
171
+
172
+ if (r ) {
173
+ rc = -1 ;
174
+ UPRINTF (LWRN , "%d-%d:%d.%d can't %s if\r\n" , b , p , c , i ,
175
+ claim == 1 ? "claim" : "release" );
176
+ }
177
+ }
178
+ if (rc )
179
+ UPRINTF (LWRN , "%d-%d fail to %s rc %d\r\n" , b , p ,
180
+ claim == 1 ? "claim" : "release" , rc );
181
+ libusb_free_config_descriptor (config );
182
+ return rc ;
183
+ }
184
+
62
185
static int
63
186
usb_dev_native_toggle_if_drivers (struct usb_dev * udev , int attach )
64
187
{
@@ -100,6 +223,220 @@ usb_dev_native_toggle_if_drivers(struct usb_dev *udev, int attach)
100
223
return rc ;
101
224
}
102
225
226
+ static void
227
+ usb_dev_set_config (struct usb_dev * udev , struct usb_data_xfer * xfer , int config )
228
+ {
229
+ int rc = 0 ;
230
+ struct libusb_config_descriptor * cfg ;
231
+
232
+ assert (udev );
233
+ assert (udev -> ldev );
234
+ assert (udev -> handle );
235
+
236
+ /*
237
+ * set configuration
238
+ * according to the libusb doc, the detach and release work
239
+ * should be done before set configuration.
240
+ */
241
+ usb_dev_native_toggle_if_drivers (udev , 0 );
242
+ usb_dev_native_toggle_if (udev , 0 );
243
+
244
+ rc = libusb_set_configuration (udev -> handle , config );
245
+ if (rc ) {
246
+ UPRINTF (LWRN , "fail to set config rc %d\r\n" , rc );
247
+ goto err2 ;
248
+ }
249
+
250
+ /* claim all the interfaces of this configuration */
251
+ rc = libusb_get_active_config_descriptor (udev -> ldev , & cfg );
252
+ if (rc ) {
253
+ UPRINTF (LWRN , "fail to get config rc %d\r\n" , rc );
254
+ goto err2 ;
255
+ }
256
+
257
+ rc = usb_dev_native_toggle_if (udev , 1 );
258
+ if (rc ) {
259
+ UPRINTF (LWRN , "fail to claim if, rc %d\r\n" , rc );
260
+ goto err1 ;
261
+ }
262
+
263
+ udev -> if_num = cfg -> bNumInterfaces ;
264
+ udev -> configuration = config ;
265
+
266
+ usb_dev_reset_ep (udev );
267
+ usb_dev_update_ep (udev );
268
+ libusb_free_config_descriptor (cfg );
269
+ return ;
270
+
271
+ err1 :
272
+ usb_dev_native_toggle_if (udev , 0 );
273
+ libusb_free_config_descriptor (cfg );
274
+ err2 :
275
+ UPRINTF (LWRN , "%d-%d: fail to set config\r\n" , udev -> bus , udev -> port );
276
+ xfer -> status = USB_ERR_STALLED ;
277
+ }
278
+
279
+ static void
280
+ usb_dev_set_if (struct usb_dev * udev , int iface , int alt , struct usb_data_xfer
281
+ * xfer )
282
+ {
283
+ assert (udev );
284
+ assert (xfer );
285
+ assert (udev -> handle );
286
+
287
+ if (iface >= USB_NUM_INTERFACE )
288
+ goto errout ;
289
+
290
+ UPRINTF (LDBG , "%d-%d set if, iface %d alt %d\r\n" , udev -> bus ,
291
+ udev -> port , iface , alt );
292
+
293
+ if (libusb_set_interface_alt_setting (udev -> handle , iface , alt ))
294
+ goto errout ;
295
+
296
+ udev -> alts [iface ] = alt ;
297
+ /*
298
+ * FIXME: Only support single interface USB device first. Need fix in
299
+ * future to support composite USB device.
300
+ */
301
+ usb_dev_reset_ep (udev );
302
+ usb_dev_update_ep (udev );
303
+ return ;
304
+
305
+ errout :
306
+ xfer -> status = USB_ERR_STALLED ;
307
+ UPRINTF (LDBG , "%d-%d fail to set if, iface %d alt %d\r\n" ,
308
+ udev -> bus , udev -> port , iface , alt );
309
+ }
310
+
311
+ static struct usb_data_xfer_block *
312
+ usb_dev_prepare_ctrl_xfer (struct usb_data_xfer * xfer )
313
+ {
314
+ int i , idx ;
315
+ struct usb_data_xfer_block * ret = NULL ;
316
+ struct usb_data_xfer_block * blk = NULL ;
317
+
318
+ idx = xfer -> head ;
319
+ for (i = 0 ; i < xfer -> ndata ; i ++ ) {
320
+ /*
321
+ * find out the data block and set every
322
+ * block to be processed
323
+ */
324
+ blk = & xfer -> data [idx ];
325
+ if (blk -> blen > 0 && !ret )
326
+ ret = blk ;
327
+
328
+ blk -> processed = 1 ;
329
+ idx = (idx + 1 ) % USB_MAX_XFER_BLOCKS ;
330
+ }
331
+ return ret ;
332
+ }
333
+
334
+ int
335
+ usb_dev_reset (void * pdata )
336
+ {
337
+ struct usb_dev * udev ;
338
+
339
+ udev = pdata ;
340
+ assert (udev );
341
+
342
+ UPRINTF (LDBG , "reset endpoints\n" );
343
+ libusb_reset_device (udev -> handle );
344
+ usb_dev_reset_ep (udev );
345
+ usb_dev_update_ep (udev );
346
+ return 0 ;
347
+ }
348
+
349
+ int
350
+ usb_dev_request (void * pdata , struct usb_data_xfer * xfer )
351
+ {
352
+ struct usb_dev * udev ;
353
+ uint8_t request_type ;
354
+ uint8_t request ;
355
+ uint16_t value ;
356
+ uint16_t index ;
357
+ uint16_t len ;
358
+ struct usb_data_xfer_block * blk ;
359
+ uint8_t * data ;
360
+ int rc ;
361
+
362
+ udev = pdata ;
363
+
364
+ assert (xfer );
365
+ assert (udev );
366
+
367
+ xfer -> status = USB_ERR_NORMAL_COMPLETION ;
368
+ if (!udev -> ldev || !xfer -> ureq ) {
369
+ UPRINTF (LWRN , "invalid request\r\n" );
370
+ xfer -> status = USB_ERR_IOERROR ;
371
+ goto out ;
372
+ }
373
+
374
+ request_type = xfer -> ureq -> bmRequestType ;
375
+ request = xfer -> ureq -> bRequest ;
376
+ value = xfer -> ureq -> wValue ;
377
+ index = xfer -> ureq -> wIndex ;
378
+ len = xfer -> ureq -> wLength ;
379
+
380
+ blk = usb_dev_prepare_ctrl_xfer (xfer );
381
+ data = blk ? blk -> buf : NULL ;
382
+
383
+ UPRINTF (LDBG ,
384
+ "urb: type 0x%x req 0x%x val 0x%x idx %d len %d data %d\n" ,
385
+ request_type , request , value , index , len ,
386
+ blk ? blk -> blen : 0 );
387
+
388
+ /*
389
+ * according to usb spec, control transfer may have no
390
+ * DATA STAGE, so the valid situations are:
391
+ * a. with DATA STAGE: blk != NULL && len > 0
392
+ * b. without DATA STAGE: blk == NULL && len == 0
393
+ * any other situations, just skip process
394
+ */
395
+ if ((!blk && len > 0 ) || (blk && len <= 0 ))
396
+ goto out ;
397
+
398
+ switch (UREQ (request , request_type )) {
399
+ case UREQ (UR_SET_ADDRESS , UT_READ_DEVICE ):
400
+ UPRINTF (LDBG , "UR_SET_ADDRESS\n" );
401
+ udev -> addr = value ;
402
+ goto out ;
403
+ case UREQ (UR_SET_CONFIG , UT_READ_DEVICE ):
404
+ UPRINTF (LDBG , "UR_SET_CONFIG\n" );
405
+ usb_dev_set_config (udev , xfer , value & 0xff );
406
+ goto out ;
407
+ case UREQ (UR_SET_INTERFACE , UT_READ_INTERFACE ):
408
+ UPRINTF (LDBG , "UR_SET_INTERFACE\n" );
409
+ usb_dev_set_if (udev , index , value , xfer );
410
+ goto out ;
411
+ case UREQ (UR_CLEAR_FEATURE , UT_WRITE_ENDPOINT ):
412
+ if (value == 0 ) {
413
+ UPRINTF (LDBG , "UR_CLEAR_HALT\n" );
414
+ libusb_clear_halt (udev -> handle , index );
415
+ goto out ;
416
+ }
417
+ }
418
+
419
+ /* send it to physical device */
420
+ /* TODO: should this be async operation? */
421
+ rc = libusb_control_transfer (udev -> handle , request_type , request ,
422
+ value , index , data , len , 100 );
423
+
424
+ if (rc >= 0 && blk ) {
425
+ blk -> blen = len - rc ;
426
+ blk -> bdone += rc ;
427
+ xfer -> status = blk -> blen > 0 ? USB_ERR_SHORT_XFER :
428
+ USB_ERR_NORMAL_COMPLETION ;
429
+ } else if (rc >= 0 )
430
+ xfer -> status = USB_ERR_NORMAL_COMPLETION ;
431
+ else
432
+ xfer -> status = usb_dev_err_convert (rc );
433
+
434
+ UPRINTF (LDBG , "usb rc %d, blk %p, blen %u bdon %u\n" , rc , blk ,
435
+ blk ? blk -> blen : 0 , blk ? blk -> bdone : 0 );
436
+ out :
437
+ return xfer -> status ;
438
+ }
439
+
103
440
void *
104
441
usb_dev_init (void * pdata , char * opt )
105
442
{
0 commit comments