/*************************************************************************//*! * * @name USB_Cdc_Ep_Mutex_Lock * * @brief The function locks the mutex for RTOS. For BM, disable interrupt. * * @param none. * @return none. * *****************************************************************************/ void USB_Cdc_Ep_Mutex_Lock(cdc_device_struct_t * cdc_obj_ptr, uint32_t ep_num) { uint8_t index, type, direction; index = USB_Map_Ep_To_Struct_Index(cdc_obj_ptr, ep_num); type = cdc_obj_ptr->ep[index].type; direction = cdc_obj_ptr->ep[index].direction; #if (((OS_ADAPTER_ACTIVE_OS == OS_ADAPTER_SDK) && (USE_RTOS))) switch(type) { case USB_BULK_PIPE: if(direction == USB_SEND) { OS_Mutex_lock(cdc_obj_ptr->send_mutex); } else if(direction == USB_RECV) { OS_Mutex_lock(cdc_obj_ptr->recv_mutex); } break; case USB_INTERRUPT_PIPE: break; default: break; } #else OS_Lock(); #endif }
/**************************************************************************//*! * * @name USB_Class_CDC_Send_Data * * @brief * * @param handle : handle returned by USB_Class_CDC_Init * @param ep_num : endpoint num * @param app_buff : buffer to send * @param size : length of the transfer * * @return status * USB_OK : When Successfull * Others : Errors *****************************************************************************/ uint_8 USB_Class_CDC_Send_Data ( CDC_HANDLE handle, uint_8 ep_num, uint_8_ptr app_buff, uint_32 size ) { #if IMPLEMENT_QUEUING uint_8 index; uint_8 producer, consumer; USB_ENDPOINTS *usb_ep_data; #endif CDC_DEVICE_STRUCT_PTR cdc_obj_ptr; uint_8 status = USB_OK; cdc_obj_ptr = USB_Cdc_Get_Device_Ptr(handle); if (NULL == cdc_obj_ptr) return USBERR_ERROR; #if IMPLEMENT_QUEUING usb_ep_data = cdc_obj_ptr->usb_ep_data; /* map the endpoint num to the index of the endpoint structure */ index = USB_Map_Ep_To_Struct_Index(cdc_obj_ptr, ep_num); producer = cdc_obj_ptr->ep[index].bin_producer; consumer = cdc_obj_ptr->ep[index].bin_consumer; if(((uint_8)(producer - consumer)) != (uint_8)(CDC_MAX_QUEUE_ELEMS)) { /* the bin is not full*/ uint_8 queue_num = (uint_8)(producer % CDC_MAX_QUEUE_ELEMS); /* put all send request parameters in the endpoint data structure*/ cdc_obj_ptr->ep[index].queue[queue_num].channel = ep_num; cdc_obj_ptr->ep[index].queue[queue_num].app_data.data_ptr = app_buff; cdc_obj_ptr->ep[index].queue[queue_num].app_data.data_size = size; cdc_obj_ptr->ep[index].queue[queue_num].handle = cdc_obj_ptr->controller_handle; /* increment producer bin by 1*/ cdc_obj_ptr->ep[index].bin_producer = ++producer; if((uint_8)(producer - consumer) == (uint_8)1) { #endif status = USB_Class_Send_Data(cdc_obj_ptr->class_handle, ep_num, app_buff,size); #if IMPLEMENT_QUEUING } } else /* bin is full */ { status = USBERR_DEVICE_BUSY; } #endif return status; }
/**************************************************************************//*! * * @name USB_Service_Hid * * @brief The function is a callback function of HID endpoint * * @param event : Pointer to USB Event Structure * * @return None * ****************************************************************************** * This function is called from lower layer when data is transfer is completed * on HID endpoint (non control endpoint) *****************************************************************************/ void USB_Service_Hid ( PTR_USB_DEV_EVENT_STRUCT event /* [IN] Pointer to USB Event Structure */ ) { uint_8 index; uint_8 producer, consumer; USB_ENDPOINTS *ep_desc_data = (USB_ENDPOINTS *) USB_Desc_Get_Endpoints(event->controller_ID); /* map the endpoint num to the index of the endpoint structure */ index = USB_Map_Ep_To_Struct_Index(event->controller_ID, event->ep_num); producer = g_hid_endpoint_data.ep[index].bin_producer; /* if there are no errors de-queue the queue and decrement the no. of transfers left, else send the same data again */ if(event->errors == 0) { /* de-queue if the send is complete without an error */ g_hid_endpoint_data.ep[index].bin_consumer++; } else { /* notify the application of the error */ g_hid_class_callback(event->controller_ID, USB_APP_ERROR, (uint_8*)(&(event->errors))); } consumer = g_hid_endpoint_data.ep[index].bin_consumer; if(consumer != producer) { /*if bin is not empty */ USB_CLASS_HID_QUEUE queue; /* send the next packet in queue */ queue = g_hid_endpoint_data.ep[index]. queue[consumer % MAX_QUEUE_ELEMS]; (void)USB_Class_Send_Data(queue.controller_ID, queue.channel, queue.app_buff, queue.size); } /* notify the app of the send complete */ g_hid_class_callback(event->controller_ID, USB_APP_SEND_COMPLETE, 0); }
/**************************************************************************//*! * * @name USB_Service_Dic_Bulk_In * * @brief The funtion ic callback function of DIC Bulk In Endpoint * * @param event * * @return None * *****************************************************************************/ void USB_Service_Dic_Bulk_In(PTR_USB_EVENT_STRUCT event,pointer arg) { APP_DATA_STRUCT bulk_in_recv; uint_8 event_type; CDC_DEVICE_STRUCT_PTR cdc_obj_ptr = (CDC_DEVICE_STRUCT_PTR)arg; #if IMPLEMENT_QUEUING uint_8 index; uint_8 producer, consumer; USB_ENDPOINTS *usb_ep_data = cdc_obj_ptr->usb_ep_data; USB_CLASS_CDC_QUEUE queue; /* map the endpoint num to the index of the endpoint structure */ index = USB_Map_Ep_To_Struct_Index(cdc_obj_ptr, event->ep_num); producer = cdc_obj_ptr->ep[index].bin_producer; /* if there are no errors de-queue the queue and decrement the no. of transfers left, else send the same data again */ cdc_obj_ptr->ep[index].bin_consumer++; consumer = cdc_obj_ptr->ep[index].bin_consumer; if(consumer != producer) {/*if bin is not empty */ queue = cdc_obj_ptr->ep[index].queue[consumer%CDC_MAX_QUEUE_ELEMS]; (void)USB_Class_Send_Data(cdc_obj_ptr->class_handle, queue.channel, queue.app_data.data_ptr, queue.app_data.data_size); } #endif if(cdc_obj_ptr->param_callback.callback != NULL) { event_type = USB_APP_SEND_COMPLETE; bulk_in_recv.data_ptr = event->buffer_ptr; bulk_in_recv.data_size = event->len; cdc_obj_ptr->param_callback.callback(event_type, (void*)&bulk_in_recv,cdc_obj_ptr->param_callback.arg); } }
/**************************************************************************//*! * * @name USB_Service_Dic_Bulk_Out * * @brief The function ic callback function of DIC Bulk Out Endpoint * * @param event * * @return None * *****************************************************************************/ void USB_Service_Dic_Bulk_Out(usb_event_struct_t* event, void* arg) { uint8_t event_type; cdc_device_struct_t * cdc_obj_ptr = (cdc_device_struct_t *)arg; //if(USB_UNINITIALIZED_VAL_32 == event->len) return; #if CDC_IMPLEMENT_QUEUING uint8_t index; uint8_t producer, consumer; cdc_queue_struct_t queue; usb_status status = USB_OK; /* map the endpoint num to the index of the endpoint structure */ index = USB_Map_Ep_To_Struct_Index(cdc_obj_ptr, event->ep_num); USB_Cdc_Ep_Mutex_Lock(cdc_obj_ptr, event->ep_num); producer = cdc_obj_ptr->ep[index].bin_producer; consumer = cdc_obj_ptr->ep[index].bin_consumer; /* No pending transfer */ if(producer == consumer) { return; } /* if there are no errors de-queue the queue and decrement the no. of transfers left, else send the same data again */ cdc_obj_ptr->ep[index].bin_consumer++; consumer = cdc_obj_ptr->ep[index].bin_consumer; while(consumer != producer) { queue = cdc_obj_ptr->ep[index].queue[consumer%CDC_MAX_QUEUE_ELEMS]; status = usb_device_recv_data(cdc_obj_ptr->controller_handle, queue.channel, queue.app_data.data_ptr, queue.app_data.data_size); if(USB_OK == status) { break; } else { USB_Cdc_Ep_Mutex_Unlock(cdc_obj_ptr, event->ep_num); if(cdc_obj_ptr->class_specific_callback.callback != NULL) { event_type = USB_DEV_EVENT_DATA_RECEIVED; event->len = 0xFFFFFFFF; cdc_obj_ptr->class_specific_callback.callback(event_type, USB_REQ_VAL_INVALID, &(event->buffer_ptr), &(event->len), cdc_obj_ptr->class_specific_callback.arg); } USB_Cdc_Ep_Mutex_Lock(cdc_obj_ptr, event->ep_num); producer = cdc_obj_ptr->ep[index].bin_producer; cdc_obj_ptr->ep[index].bin_consumer++; consumer = cdc_obj_ptr->ep[index].bin_consumer; } } USB_Cdc_Ep_Mutex_Unlock(cdc_obj_ptr, event->ep_num); #endif if (cdc_obj_ptr->class_specific_callback.callback != NULL) { event_type = USB_DEV_EVENT_DATA_RECEIVED; cdc_obj_ptr->class_specific_callback.callback(event_type, USB_REQ_VAL_INVALID, &(event->buffer_ptr), &(event->len), cdc_obj_ptr->class_specific_callback.arg); } }
/**************************************************************************//*! * * @name USB_Service_Cdc_Notif * * @brief The function ic callback function of CIC Notification endpoint * * @param event * * @return None * *****************************************************************************/ void USB_Service_Cdc_Notif(usb_event_struct_t* event, void* arg) { cdc_device_struct_t * cdc_obj_ptr = (cdc_device_struct_t *)arg; #if CDC_IMPLEMENT_QUEUING uint8_t index; uint8_t producer, consumer; // usb_endpoints_t *usb_ep_data = cdc_obj_ptr->usb_ep_data; cdc_queue_struct_t queue; usb_status status = USB_OK; #endif //UNUSED_ARGUMENT (event) #if CDC_IMPLEMENT_QUEUING /* map the endpoint num to the index of the endpoint structure */ index = USB_Map_Ep_To_Struct_Index(cdc_obj_ptr, event->ep_num); USB_Cdc_Ep_Mutex_Lock(cdc_obj_ptr, event->ep_num); producer = cdc_obj_ptr->ep[index].bin_producer; consumer = cdc_obj_ptr->ep[index].bin_consumer; /* No pending transfer */ if(producer == consumer) { return; } /* if there are no errors de-queue the queue and decrement the no. of transfers left, else send the same data again */ cdc_obj_ptr->ep[index].bin_consumer++; consumer = cdc_obj_ptr->ep[index].bin_consumer; while(consumer != producer) { queue = cdc_obj_ptr->ep[index].queue[consumer%CDC_MAX_QUEUE_ELEMS]; status = USB_Class_Send_Data(cdc_obj_ptr->class_handle, queue.channel, queue.app_data.data_ptr, queue.app_data.data_size); if(USB_OK == status) { break; } else { USB_Cdc_Ep_Mutex_Unlock(cdc_obj_ptr, event->ep_num); if(cdc_obj_ptr->class_specific_callback.callback != NULL) { uint8_t event_type = USB_APP_CDC_SERIAL_STATE_NOTIF; event->len = 0xFFFFFFFF; cdc_obj_ptr->class_specific_callback.callback(event_type, USB_REQ_VAL_INVALID, NULL, &(event->len), cdc_obj_ptr->class_specific_callback.arg); } USB_Cdc_Ep_Mutex_Lock(cdc_obj_ptr, event->ep_num); producer = cdc_obj_ptr->ep[index].bin_producer; cdc_obj_ptr->ep[index].bin_consumer++; consumer = cdc_obj_ptr->ep[index].bin_consumer; } } USB_Cdc_Ep_Mutex_Unlock(cdc_obj_ptr, event->ep_num); #endif cdc_obj_ptr->has_sent_state = FALSE; if (cdc_obj_ptr->class_specific_callback.callback != NULL) { uint8_t event_type = USB_APP_CDC_SERIAL_STATE_NOTIF; cdc_obj_ptr->class_specific_callback.callback(event_type, USB_REQ_VAL_INVALID, &(event->buffer_ptr), &(event->len), cdc_obj_ptr->class_specific_callback.arg); } }