/* ** =================================================================== ** Method : usb_mems_USB_Class_Mems_Send_Data (component USB_MEMS_CLASS) ** Description : ** This fucntion is used by Application to send data through ** Mems class ** Parameters : ** NAME - DESCRIPTION ** controller_ID - ** ep_num - ** app_buff - ** size - ** Returns : ** --- - Error code ** =================================================================== */ uint_8 USB_Class_Mems_Send_Data( uint_8 controller_ID, uint_8 ep_num, uint_8_ptr app_buff, USB_PACKET_SIZE size ) { uint_8 status = USB_OK; PTR_USB_CLASS_MEMS_QUEUE queue_tmp; uint_8 index; uint_8 producer, queue_num; USB_ENDPOINTS *usb_ep_data = (USB_ENDPOINTS *) USB_Desc_Get_Endpoints(controller_ID); /* map the endpoint num to the index of the endpoint structure */ for(index = 0; index < usb_ep_data->count; index++) { if(usb_ep_data->ep[index].ep_num == ep_num) break; } producer = g_mems_endpoint_data.ep[index].bin_producer; queue_num = g_mems_endpoint_data.ep[index].queue_num; //if queue_num==1,there is already a queue,USB is busy //if queue_num!=1,there USB queue is empty if(MAX_QUEUE_ELEMS != queue_num) { /* the bin is not full*/ /* put all send request parameters in the endpoint data structure */ queue_tmp = &(g_mems_endpoint_data.ep[index].queue[producer]); queue_tmp->controller_ID = controller_ID; queue_tmp->channel = ep_num; queue_tmp->app_buff = app_buff; queue_tmp->size = size; /* increment producer bin by 1*/ if (producer == (MAX_QUEUE_ELEMS - 1)) { g_mems_endpoint_data.ep[index].bin_producer = 0; } else { g_mems_endpoint_data.ep[index].bin_producer++; } g_mems_endpoint_data.ep[index].queue_num++; if(g_mems_endpoint_data.ep[index].queue_num == 1) { status = USB_Class_Send_Data(controller_ID, ep_num, app_buff,size); } } else /* bin is full */ { status = USBERR_DEVICE_BUSY; } return status; }
/**************************************************************************//*! * * @name USB_Service_Video_Isochronous * * @brief The funtion ic callback function of Video Isochronous IN endpoint * * @param event * * @return None * **************************************************************************** * The function is called in response to Isochronous IN Service ******************************************************************************/ void USB_Service_Video_Isochronous(PTR_USB_DEV_EVENT_STRUCT event) { #if IMPLEMENT_QUEUING uint_8 index; uint_8 producer, consumer; /*Body*/ USB_ENDPOINTS *usb_ep_data = (USB_ENDPOINTS *) USB_Desc_Get_Endpoints(event->controller_ID); /* map the endpoint num to the index of the endpoint structure */ for(index = 0; index < usb_ep_data->count; index++) { if(usb_ep_data->ep[index].ep_num ==event->ep_num) break; }/*EndFor*/ producer = g_video_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 */ if ((MAX_QUEUE_ELEMS-1) == g_video_endpoint_data.ep[index].bin_consumer) { g_video_endpoint_data.ep[index].bin_consumer = 0; } else { g_video_endpoint_data.ep[index].bin_consumer++; }/*EndIf*/ g_video_endpoint_data.ep[index].queue_num--; }/*EndIf*/ consumer = g_video_endpoint_data.ep[index].bin_consumer; if(0 != g_video_endpoint_data.ep[index].queue_num) { /*if bin is not empty */ USB_CLASS_VIDEO_QUEUE queue; /* send the next packet in queue */ queue = g_video_endpoint_data.ep[index].queue[consumer]; (void)USB_Class_Send_Data(queue.controller_ID, queue.channel, queue.app_buff, queue.size); }/*EndIf*/ #endif if(g_video_class_callback != NULL) { uint_8 event_type = USB_APP_SEND_COMPLETE; if(event->errors != 0) { event_type = USB_APP_ERROR; }/*EndIf*/ g_video_class_callback(event->controller_ID, event_type, (uint_8*)(&(event->errors))); }/*EndIf*/ }/*EndBody*/
/**************************************************************************//*! * * @name USB_Class_CDC_Service_Dic_Bulk_In * * @brief The funtion is callback function of DIC Bulk In Endpoint * * @param event : Pointer to USB Event Structure * * @return None * ****************************************************************************** * Called by Lower Layer when Data on DIC SEND Interface is sent *****************************************************************************/ static void USB_Class_CDC_Service_Dic_Bulk_In ( PTR_USB_DEV_EVENT_STRUCT event /* [IN] Pointer to USB Event Structure */ ) { APP_DATA_STRUCT bulk_in_recv; #if IMPLEMENT_QUEUING uint_8 index; uint_8 producer, consumer; USB_ENDPOINTS *usb_ep_data = (USB_ENDPOINTS *) USB_Desc_Get_Endpoints(event->controller_ID); USB_CLASS_CDC_QUEUE queue; bulk_in_recv.data_ptr = event->buffer_ptr; bulk_in_recv.data_size = event->len; /* map the endpoint num to the index of the endpoint structure */ for(index = 0; index < usb_ep_data->count; index++) { if(usb_ep_data->ep[index].ep_num == event->ep_num) break; } producer = g_cdc_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) { g_cdc_ep[index].bin_consumer++; } consumer = g_cdc_ep[index].bin_consumer; if(consumer != producer) {/*if bin is not empty */ queue = g_cdc_ep[index].queue[consumer%MAX_QUEUE_ELEMS]; (void)USB_Class_Send_Data(queue.controller_ID, queue.channel, queue.app_data.data_ptr, queue.app_data.data_size); } #endif if(g_cdc_class_callback != NULL) { if(event->errors != 0) { g_cdc_class_callback(event->controller_ID, USB_APP_ERROR, (uint_8*)(&(event->errors))); } else { g_cdc_class_callback(event->controller_ID, USB_APP_SEND_COMPLETE, (void*)&bulk_in_recv); } } }
/**************************************************************************//*! * * @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_Class_CDC_Send_Data * * @brief This function is used to send data from CDC Class over send endpoints * * @param controller_ID : Controller ID * @param ep_num : Endpoint number * @param app_buff : Buffer to send * @param size : Length of the transfer * * @return status * USB_OK : When Successfull * Others : Errors ****************************************************************************** * Helper function. Sends DATA over CIC and DIC Interfaces to Host *****************************************************************************/ uint_8 USB_Class_CDC_Send_Data ( uint_8 controller_ID, /* [IN] Controller ID */ uint_8 ep_num, /* [IN] Endpoint Number */ uint_8_ptr app_buff, /* Pointer to Application Buffer */ USB_PACKET_SIZE size /* Size of Application Buffer */ ) { uint_8 status = USB_OK; #if IMPLEMENT_QUEUING uint_8 index; uint_8 producer, consumer; USB_ENDPOINTS *usb_ep_data = (USB_ENDPOINTS *) USB_Desc_Get_Endpoints(controller_ID); /* map the endpoint num to the index of the endpoint structure */ for(index = 0; index < usb_ep_data->count; index++) { if(usb_ep_data->ep[index].ep_num == ep_num) { break; } } producer = g_cdc_ep[index].bin_producer; consumer = g_cdc_ep[index].bin_consumer; if(((uint_8)(producer - consumer)) != (uint_8)(MAX_QUEUE_ELEMS)) { /* the bin is not full*/ uint_8 queue_num = (uint_8)(producer % MAX_QUEUE_ELEMS); /* put all send request parameters in the endpoint data structure */ g_cdc_ep[index].queue[queue_num].controller_ID = controller_ID; g_cdc_ep[index].queue[queue_num].channel = ep_num; g_cdc_ep[index].queue[queue_num].app_data.data_ptr = app_buff; g_cdc_ep[index].queue[queue_num].app_data.data_size = size; /* increment producer bin by 1*/ g_cdc_ep[index].bin_producer = ++producer; if((uint_8)(producer - consumer) == (uint_8)1) { #endif status = USB_Class_Send_Data(controller_ID, ep_num, app_buff,size); #if IMPLEMENT_QUEUING } } else /* bin is full */ { status = USBERR_DEVICE_BUSY; } #endif return status; }
/* ** =================================================================== ** Method : USB_Service_Mems_Status_Interrupt (component USB_MEMS_CLASS) ** ** Description : ** The funtion is callback function of Mems Status Interrupt ** endpoint ** This method is internal. It is used by Processor Expert only. ** =================================================================== */ static void USB_Service_Mems_Status_Interrupt( PTR_USB_DEV_EVENT_STRUCT event ) { uint_8 index; uint_8 producer, consumer; USB_ENDPOINTS *usb_ep_data = (USB_ENDPOINTS *)USB_Desc_Get_Endpoints(event->controller_ID); /* map the endpoint num to the index of the endpoint structure */ for(index = 0; index < usb_ep_data->count; index++) { if(usb_ep_data->ep[index].ep_num == event->ep_num) break; } producer = g_mems_endpoint_data.ep[index].bin_producer; consumer = g_mems_endpoint_data.ep[index].bin_consumer; /* 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 */ if((MAX_QUEUE_ELEMS-1) == consumer) { g_mems_endpoint_data.ep[index].bin_consumer = 0; } else { g_mems_endpoint_data.ep[index].bin_consumer++; } } consumer = g_mems_endpoint_data.ep[index].bin_consumer; g_mems_endpoint_data.ep[index].queue_num--; if(0 == g_mems_endpoint_data.ep[index].queue_num) { /*if bin is not empty */ USB_CLASS_MEMS_QUEUE queue; /* send the next packet in queue */ queue = g_mems_endpoint_data.ep[index].queue[consumer]; (void)USB_Class_Send_Data(queue.controller_ID, queue.channel, queue.app_buff, queue.size); } if(g_param_callback != NULL) { uint_8 event_type = USB_APP_SEND_COMPLETE; if(event->errors != 0) { event_type = USB_APP_ERROR; } g_param_callback(event->controller_ID, event_type, (uint_8*)(&(event->errors))); } }
/**************************************************************************//*! * * @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_Hid * * @brief The funtion ic callback function of HID endpoint * * @param event * * @return None * *****************************************************************************/ void USB_Service_Hid(PTR_USB_EVENT_STRUCT event,pointer arg) { uint_8 index; uint_8 producer, consumer; HID_DEVICE_STRUCT_PTR devicePtr; USB_ENDPOINTS *ep_desc_data; devicePtr = (HID_DEVICE_STRUCT_PTR)arg; ep_desc_data = devicePtr->ep_desc_data; /* map the endpoint num to the index of the endpoint structure */ index = HID_USB_Map_Ep_To_Struct_Index(devicePtr, event->ep_num); producer = devicePtr->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 */ /* de-queue if the send is complete with no error */ devicePtr->hid_endpoint_data.ep[index].bin_consumer++; consumer = devicePtr->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 = devicePtr->hid_endpoint_data.ep[index]. queue[consumer % HID_MAX_QUEUE_ELEMS]; (void)USB_Class_Send_Data(devicePtr->class_handle, queue.channel, queue.app_buff, queue.size); } /* notify the app of the send complete */ devicePtr->hid_class_callback.callback(USB_APP_SEND_COMPLETE, 0, devicePtr->hid_class_callback.arg); }
/**************************************************************************//*! * * @name USB_Class_CDC_Service_Cic_Notify * * @brief The function is callback function of CIC Notification endpoint * * @param event : Pointer to USB Event Structure * * @return None * ****************************************************************************** * Called by Lower layer when data on CIC Endpoint is sent *****************************************************************************/ void USB_Class_CDC_Service_Cic_Notify ( PTR_USB_DEV_EVENT_STRUCT event /* [IN] Pointer to USB Event Structure */ ) { #if IMPLEMENT_QUEUING uint_8 index; uint_8 producer, consumer; USB_ENDPOINTS *usb_ep_data = (USB_ENDPOINTS *) USB_Desc_Get_Endpoints(event->controller_ID); USB_CLASS_CDC_QUEUE queue; /* map the endpoint num to the index of the endpoint structure */ for(index = 0; index < usb_ep_data->count; index++) { if(usb_ep_data->ep[index].ep_num == event->ep_num) break; } producer = g_cdc_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) { g_cdc_ep[index].bin_consumer++; } consumer = g_cdc_ep[index].bin_consumer; if(consumer != producer) {/*if bin is not empty */ queue = g_cdc_ep[index].queue[consumer%%MAX_QUEUE_ELEMS]; (void)USB_Class_Send_Data(queue.controller_ID, queue.channel, queue.app_data.data_ptr, queue.app_data.data_size); }
/**************************************************************************//*! * * @name USB_Service_Dic_Bulk_In * * @brief The function ic callback function of DIC Bulk In Endpoint * * @param event * * @return None * *****************************************************************************/ void USB_Service_Dic_Bulk_In(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; // usb_endpoints_t *usb_ep_data = cdc_obj_ptr->usb_ep_data; 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_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) { event_type = USB_DEV_EVENT_SEND_COMPLETE; 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_SEND_COMPLETE; 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_Class_Video_Send_Data * * @brief This fucntion is used by Application to send data through Video class * * @param controller_ID : Controller ID * @param ep_num : Endpoint number * @param app_buff : Buffer to send * @param size : Length of the transfer * * @return status: * USB_OK : When Successfull * Others : When Error * ****************************************************************************** * This fucntion is used by Application to send data through Video class *****************************************************************************/ uint_8 USB_Class_Video_Send_Data ( uint_8 controller_ID, /* [IN] Controller ID */ uint_8 ep_num, /* [IN] Endpoint Number */ uint_8_ptr app_buff, /* [IN] Buffer to Send */ USB_PACKET_SIZE size /* [IN] Length of the Transfer */ ) { uint_8 status = USB_OK; PTR_USB_CLASS_VIDEO_QUEUE queue_tmp; #if IMPLEMENT_QUEUING uint_8 index; uint_8 producer, queue_num; USB_ENDPOINTS *usb_ep_data = (USB_ENDPOINTS *) USB_Desc_Get_Endpoints(controller_ID); /*Body*/ /* map the endpoint num to the index of the endpoint structure */ for(index = 0; index < usb_ep_data->count; index++) { if(usb_ep_data->ep[index].ep_num == ep_num) break; }/*EndFor*/ producer = g_video_endpoint_data.ep[index].bin_producer; queue_num = g_video_endpoint_data.ep[index].queue_num; if(MAX_QUEUE_ELEMS != queue_num) { /* the bin is not full*/ /* put all send request parameters in the endpoint data structure */ queue_tmp = &(g_video_endpoint_data.ep[index].queue[producer]); queue_tmp->controller_ID = controller_ID; queue_tmp->channel = ep_num; queue_tmp->app_buff = app_buff; queue_tmp->size = size; /* increment producer bin by 1*/ if (producer == (MAX_QUEUE_ELEMS - 1)) { g_video_endpoint_data.ep[index].bin_producer = 0; } /*Else*/ else { g_video_endpoint_data.ep[index].bin_producer++; }/*EndElse*/ g_video_endpoint_data.ep[index].queue_num++; if(g_video_endpoint_data.ep[index].queue_num == 1) { #endif status = USB_Class_Send_Data(controller_ID, ep_num, app_buff,size); #if IMPLEMENT_QUEUING }/*EndIf*/ }/*Else*/ else /* bin is full */ { status = USBERR_DEVICE_BUSY; }/*EndIf*/ #endif return status; }/*EndBody*/