75
75
#define EP_IS_IN (ep ) (((ep) & USB_EP_DIR_MASK) == USB_EP_DIR_IN)
76
76
#define EP_IS_OUT (ep ) (((ep) & USB_EP_DIR_MASK) == USB_EP_DIR_OUT)
77
77
78
+ /* Transfer completion callback */
79
+ typedef void (* usb_dc_transfer_callback )(u8_t ep , int status , size_t tsize );
80
+
78
81
/* Endpoint state */
79
82
struct usb_dc_stm32_ep_state {
80
83
u16_t ep_mps ; /** Endpoint max packet size */
@@ -83,7 +86,11 @@ struct usb_dc_stm32_ep_state {
83
86
u8_t ep_stalled ; /** Endpoint stall flag */
84
87
u32_t read_count ; /** Number of bytes in read buffer */
85
88
u32_t read_offset ; /** Current offset in read buffer */
86
- struct k_sem write_sem ; /** Write boolean semaphore */
89
+ u8_t * transfer_buf ; /** IN/OUT transfer buffer */
90
+ u32_t transfer_size ; /** number of bytes processed by the tranfer */
91
+ int transfer_result ; /** Transfer result */
92
+ usb_dc_transfer_callback transfer_cb ; /** Transfer callback */
93
+ struct k_sem transfer_sem ; /** transfer boolean semaphore */
87
94
};
88
95
89
96
/* Driver state */
@@ -172,7 +179,10 @@ static int usb_dc_stm32_init(void)
172
179
for (i = 0 ; i < CONFIG_USB_DC_STM32_EP_NUM ; i ++ ) {
173
180
HAL_PCDEx_SetTxFiFo (& usb_dc_stm32_state .pcd , i ,
174
181
FIFO_EP_WORDS );
175
- k_sem_init (& usb_dc_stm32_state .in_ep_state [i ].write_sem , 1 , 1 );
182
+ k_sem_init (& usb_dc_stm32_state .in_ep_state [i ].transfer_sem , 1 ,
183
+ 1 );
184
+ k_sem_init (& usb_dc_stm32_state .out_ep_state [i ].transfer_sem , 1 ,
185
+ 1 );
176
186
}
177
187
178
188
IRQ_CONNECT (STM32F4_IRQ_OTG_FS , CONFIG_USB_DC_STM32_IRQ_PRI ,
@@ -243,10 +253,105 @@ int usb_dc_set_address(const u8_t addr)
243
253
return 0 ;
244
254
}
245
255
246
- int usb_dc_ep_start_read (u8_t ep , u8_t * data , u32_t max_data_len )
256
+ static int usb_dc_ep_transfer (const u8_t ep , u8_t * buf , size_t dlen , bool is_in ,
257
+ usb_dc_transfer_callback cb )
247
258
{
259
+ struct usb_dc_stm32_ep_state * ep_state = usb_dc_stm32_get_ep_state (ep );
248
260
HAL_StatusTypeDef status ;
261
+ int ret = 0 ;
262
+
263
+ SYS_LOG_DBG ("ep 0x%02x, len=%d, in=%d, sync=%s" , ep , dlen , is_in ,
264
+ cb ? "no" : "yes" );
265
+
266
+ if (!dlen && !is_in ) {
267
+ HAL_PCD_EP_Receive (& usb_dc_stm32_state .pcd , ep , NULL , 0 );
268
+ return 0 ;
269
+ }
270
+
271
+ /* Transfer Already Ongoing ? */
272
+ if (k_sem_take (& ep_state -> transfer_sem , K_NO_WAIT )) {
273
+ return - EBUSY ;
274
+ }
275
+
276
+ ep_state -> transfer_buf = buf ;
277
+ ep_state -> transfer_result = - EBUSY ;
278
+ ep_state -> transfer_size = dlen ;
279
+ ep_state -> transfer_cb = cb ;
280
+
281
+ if (!k_is_in_isr ()) {
282
+ irq_disable (STM32F4_IRQ_OTG_FS );
283
+ }
284
+
285
+ /* Configure and start transfer */
286
+ if (is_in ) { /* DEV to HOST */
287
+ status = HAL_PCD_EP_Transmit (& usb_dc_stm32_state .pcd , ep ,
288
+ ep_state -> transfer_buf , dlen );
289
+ } else { /* HOST TO DEV */
290
+ status = HAL_PCD_EP_Receive (& usb_dc_stm32_state .pcd , ep ,
291
+ ep_state -> transfer_buf , dlen );
292
+ }
293
+
294
+ if (status != HAL_OK ) {
295
+ SYS_LOG_ERR ("ep 0x%02x, transfer error %d" , ep , ret );
296
+ ep_state -> transfer_buf = NULL ;
297
+ ret = - EIO ;
298
+ }
299
+
300
+ if (!k_is_in_isr ()) {
301
+ irq_enable (STM32F4_IRQ_OTG_FS );
302
+ }
303
+
304
+ if (ep_state -> transfer_cb || ret ) { /* asynchronous transfer or error */
305
+ return ret ;
306
+ }
307
+
308
+ /* Synchronous transfer */
309
+ if (k_sem_take (& ep_state -> transfer_sem , K_FOREVER )) {
310
+ SYS_LOG_ERR ("ep 0x%02x, transfer error" , ep );
311
+ ep_state -> transfer_buf = NULL ;
312
+ return - ETIMEDOUT ;
313
+ }
314
+
315
+ if (ep_state -> transfer_result ) { /* error < 0 */
316
+ ret = ep_state -> transfer_result ;
317
+ } else { /* synchronous transfer success, return processed bytes */
318
+ ret = ep_state -> transfer_size ;
319
+ }
320
+
321
+ k_sem_give (& ep_state -> transfer_sem );
322
+
323
+ return ret ;
324
+ }
325
+
326
+ static void __legacy_out_cb (u8_t ep , int status , size_t tsize )
327
+ {
328
+ struct usb_dc_stm32_ep_state * ep_state = usb_dc_stm32_get_ep_state (ep );
329
+
330
+ ARG_UNUSED (status );
331
+
332
+ /* Transfer completed, data is stored in our legacy endpoint buffer */
333
+ ep_state -> read_count = tsize ;
334
+ ep_state -> read_offset = 0 ;
335
+
336
+ if (ep_state -> cb ) {
337
+ ep_state -> cb (ep , USB_DC_EP_DATA_OUT );
338
+ }
339
+ }
249
340
341
+ static void __legacy_in_cb (u8_t ep , int status , size_t tsize )
342
+ {
343
+ struct usb_dc_stm32_ep_state * ep_state = usb_dc_stm32_get_ep_state (ep );
344
+
345
+ ARG_UNUSED (status );
346
+ ARG_UNUSED (tsize );
347
+
348
+ if (ep_state -> cb ) {
349
+ ep_state -> cb (ep , USB_DC_EP_DATA_IN );
350
+ }
351
+ }
352
+
353
+ int usb_dc_ep_start_read (u8_t ep , u8_t * data , u32_t max_data_len )
354
+ {
250
355
SYS_LOG_DBG ("ep 0x%02x, len %u" , ep , max_data_len );
251
356
252
357
/* we flush EP0_IN by doing a 0 length receive on it */
@@ -259,16 +364,9 @@ int usb_dc_ep_start_read(u8_t ep, u8_t *data, u32_t max_data_len)
259
364
max_data_len = USB_OTG_FS_MAX_PACKET_SIZE ;
260
365
}
261
366
262
- status = HAL_PCD_EP_Receive (& usb_dc_stm32_state .pcd , ep ,
263
- usb_dc_stm32_state .ep_buf [EP_IDX (ep )],
264
- max_data_len );
265
- if (status != HAL_OK ) {
266
- SYS_LOG_ERR ("HAL_PCD_EP_Receive failed(0x%02x), %d" ,
267
- ep , (int )status );
268
- return - EIO ;
269
- }
270
-
271
- return 0 ;
367
+ /* asynchronous out transfer to keep legacy behaviour */
368
+ return usb_dc_ep_transfer (ep , data , max_data_len , false,
369
+ __legacy_out_cb );
272
370
}
273
371
274
372
int usb_dc_ep_get_read_count (u8_t ep , u32_t * read_bytes )
@@ -440,8 +538,6 @@ int usb_dc_ep_disable(const u8_t ep)
440
538
int usb_dc_ep_write (const u8_t ep , const u8_t * const data ,
441
539
const u32_t data_len , u32_t * const ret_bytes )
442
540
{
443
- struct usb_dc_stm32_ep_state * ep_state = usb_dc_stm32_get_ep_state (ep );
444
- HAL_StatusTypeDef status ;
445
541
int ret = 0 ;
446
542
447
543
SYS_LOG_DBG ("ep 0x%02x, len %u" , ep , data_len );
@@ -451,24 +547,14 @@ int usb_dc_ep_write(const u8_t ep, const u8_t *const data,
451
547
return - EINVAL ;
452
548
}
453
549
454
- ret = k_sem_take (& ep_state -> write_sem , 1000 );
455
- if (ret ) {
456
- SYS_LOG_ERR ("Unable to write ep 0x%02x (%d)" , ep , ret );
457
- return ret ;
458
- }
459
-
460
- if (!k_is_in_isr ()) {
461
- irq_disable (STM32F4_IRQ_OTG_FS );
462
- }
463
-
464
- status = HAL_PCD_EP_Transmit (& usb_dc_stm32_state .pcd , ep ,
465
- (void * )data , data_len );
466
- if (status != HAL_OK ) {
467
- SYS_LOG_ERR ("HAL_PCD_EP_Transmit failed(0x%02x), %d" ,
468
- ep , (int )status );
469
- k_sem_give (& ep_state -> write_sem );
470
- ret = - EIO ;
471
- }
550
+ do {
551
+ /* For now we want to preserve legacy ep_write behavior.
552
+ * If ep transfer fails due to ongoing transfer, try again.
553
+ */
554
+ ret = usb_dc_ep_transfer (ep , (u8_t * )data , data_len , true,
555
+ __legacy_in_cb );
556
+ k_yield ();
557
+ } while (ret == - EBUSY );
472
558
473
559
if (!ret && ep == EP0_IN ) {
474
560
/* Wait for an empty package as from the host.
@@ -477,10 +563,6 @@ int usb_dc_ep_write(const u8_t ep, const u8_t *const data,
477
563
usb_dc_ep_start_read (ep , NULL , 0 );
478
564
}
479
565
480
- if (!k_is_in_isr ()) {
481
- irq_enable (STM32F4_IRQ_OTG_FS );
482
- }
483
-
484
566
if (ret_bytes ) {
485
567
* ret_bytes = data_len ;
486
568
}
@@ -639,14 +721,17 @@ void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, u8_t epnum)
639
721
SYS_LOG_DBG ("epnum 0x%02x, rx_count %u" , epnum ,
640
722
HAL_PCD_EP_GetRxCount (& usb_dc_stm32_state .pcd , epnum ));
641
723
642
- /* Transaction complete, data is now stored in the buffer and ready
643
- * for the upper stack (usb_dc_ep_read to retrieve).
644
- */
645
- usb_dc_ep_get_read_count (ep , & ep_state -> read_count );
646
- ep_state -> read_offset = 0 ;
724
+ if (!ep_state -> transfer_buf ) { /* ignore if no transfer buffer */
725
+ return ;
726
+ }
647
727
648
- if (ep_state -> cb ) {
649
- ep_state -> cb (ep , USB_DC_EP_DATA_OUT );
728
+ ep_state -> transfer_buf = NULL ;
729
+ ep_state -> transfer_result = 0 ;
730
+ usb_dc_ep_get_read_count (ep , & ep_state -> transfer_size );
731
+ k_sem_give (& ep_state -> transfer_sem );
732
+
733
+ if (ep_state -> transfer_cb ) {
734
+ ep_state -> transfer_cb (ep , 0 , ep_state -> transfer_size );
650
735
}
651
736
}
652
737
@@ -658,9 +743,15 @@ void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, u8_t epnum)
658
743
659
744
SYS_LOG_DBG ("epnum 0x%02x" , epnum );
660
745
661
- k_sem_give (& ep_state -> write_sem );
746
+ if (!ep_state -> transfer_buf ) { /* ignore if no transfer buffer */
747
+ return ;
748
+ }
662
749
663
- if (ep_state -> cb ) {
664
- ep_state -> cb (ep , USB_DC_EP_DATA_IN );
750
+ ep_state -> transfer_buf = NULL ;
751
+ ep_state -> transfer_result = 0 ;
752
+ k_sem_give (& ep_state -> transfer_sem );
753
+
754
+ if (ep_state -> transfer_cb ) {
755
+ ep_state -> transfer_cb (ep , 0 , ep_state -> transfer_size );
665
756
}
666
757
}
0 commit comments