I am beginning to learn how USB is implemented in MC9S08JM32. I was reading thru the code but couldn't quite understand it: the codes are pasted as follows.
What is the purpose of USB_Class_Init() and USB_Class_Hid_Event()?
uint_8 USB_Class_HID_Init ( uint_8 controller_ID, /* [IN] Controller ID */ USB_CLASS_CALLBACK hid_class_callback, /* [IN] HID Class Callback */ USB_REQ_FUNC vendor_req_callback, /* [IN] Vendor Request Callback */ USB_CLASS_SPECIFIC_HANDLER_FUNC param_callback /* [ IN] HID Class requests Callback */){ uint_8 index; USB_ENDPOINTS *ep_desc_data = (USB_ENDPOINTS *) USB_Desc_Get_Endpoints(controller_ID); /* Initialize the device layer*/ uint_8 status = USB_Device_Init(controller_ID, (uint_8)(ep_desc_data->count+1)); if(status == USB_OK) { /* Initialize the generic class functions */ status = USB_Class_Init(controller_ID,USB_Class_Hid_Event, USB_Other_Requests); if(status == USB_OK) { g_hid_endpoint_data.count = ep_desc_data->count; for(index = 0; index < ep_desc_data->count; index++) { g_hid_endpoint_data.ep[index].endpoint = ep_desc_data->ep[index].ep_num; g_hid_endpoint_data.ep[index].type = ep_desc_data->ep[index].type; g_hid_endpoint_data.ep[index].bin_consumer = 0x00; g_hid_endpoint_data.ep[index].bin_producer = 0x00; } /* save the HID class callback pointer */ g_hid_class_callback = hid_class_callback; /* save the vendor request callback pointer */ g_vendor_req_callback = vendor_req_callback; /* Save the callback to ask application for class specific params*/ g_param_callback = param_callback; } } return status;}
uint_8 USB_Class_Init ( uint_8 controller_ID, /* [IN] Controller ID */ USB_CLASS_CALLBACK class_callback, /* [IN] Class Callback */ USB_REQ_FUNC other_req_callback /* [IN] Other Requests Callback */){ uint_8 status = USB_Framework_Init(controller_ID,class_callback, other_req_callback); /* save callback address */ g_class_callback = class_callback; if(status == USB_OK) { /* Register all the services here */ status |= USB_Device_Register_Service(controller_ID, USB_SERVICE_BUS_RESET, USB_Reset_Service); status |= USB_Device_Register_Service(controller_ID, USB_SERVICE_SOF,USB_Sof_Service); status |= USB_Device_Register_Service(controller_ID, USB_SERVICE_SLEEP,USB_Suspend_Service); status |= USB_Device_Register_Service(controller_ID, USB_SERVICE_RESUME,USB_Resume_Service); status |= USB_Device_Register_Service(controller_ID, USB_SERVICE_STALL,USB_Stall_Service); status |= USB_Device_Register_Service(controller_ID, USB_SERVICE_ERROR,USB_Error_Service); /* set the device state as powered */ (void)USB_Device_Set_Status(controller_ID, USB_STATUS_DEVICE_STATE,USB_STATE_POWERED); g_device_state_before_suspend = USB_STATE_POWERED; } return status;}
static void USB_Class_Hid_Event ( uint_8 controller_ID, /* [IN] Controller ID */ uint_8 event, /* [IN] Event Type */ void* val /* [IN] Pointer to configuration Value */){ uint_8 index; if(event == USB_APP_ENUM_COMPLETE) { uint_8 count; /* get the endpoints from the descriptor module */ USB_ENDPOINTS *ep_desc_data = (USB_ENDPOINTS *) USB_Desc_Get_Endpoints(controller_ID); count = ep_desc_data->count; /* deinitialize all endpoints in case they were initialized */ while(count > 0) { USB_EP_STRUCT_PTR ep_struct_ptr= (USB_EP_STRUCT_PTR) (&ep_desc_data->ep[count - 1]); (void)USB_Device_Deinit_EndPoint(controller_ID, ep_struct_ptr->ep_num, ep_struct_ptr->direction); count--; } /* intialize all non control endpoints */ while(count < ep_desc_data->count) { USB_EP_STRUCT_PTR ep_struct= (USB_EP_STRUCT_PTR)&ep_desc_data->ep[count]; (void)USB_Device_Init_EndPoint(controller_ID, ep_struct, TRUE); /* register callback service for the endpoint */ (void)USB_Device_Register_Service(controller_ID, (uint_8)(USB_SERVICE_EP0+ep_struct->ep_num), USB_Service_Hid); /* set the EndPoint Status as Idle in the device layer */ (void)USB_Device_Set_Status(controller_ID, (uint_8)(USB_STATUS_ENDPOINT | (HID_ENDPOINT + (ep_struct->ep_num - 1)) | (ep_struct->direction << USB_COMPONENT_DIRECTION_SHIFT)), USB_STATUS_IDLE); count++; } } else if(event == USB_APP_BUS_RESET) { /* clear producer and consumer on reset */ for(index = 0; index < g_hid_endpoint_data.count; index++) { g_hid_endpoint_data.ep[index].bin_consumer = 0x00; g_hid_endpoint_data.ep[index].bin_producer = 0x00; } } if(g_hid_class_callback != NULL) { /* notify the application of the event */ g_hid_class_callback(controller_ID, event, val); }}
I don't know who made this one, but a horrible implementation.
He want to introduce layered architecture to the USB device stack, and failed. Processes which should be placed in a lower layer are spilled out into upper layer. 90% of this code is useless. Most of the code is there just to maintain his layered architecture. It does nothing useful for real USB implementation. This is a typical case, in which half-baked understanding makes things more complicated. Trash them all. It makes you confused.
The source code in CMX_USB-LITE is much better than this one. You'll get better perspective with this one.
http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=CMX_USB-LITE
Tsuneo