/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_dev_list_attach_device * Returned Value : * Comments : * This function will be called when attach interrupt happens, to * add onto the device list and do common initialization. * *END*--------------------------------------------------------------------*/ USB_STATUS usb_dev_list_attach_device ( _usb_host_handle handle, uint_8 speed, uint_8 hub_no, uint_8 port_no ) { /* Body */ USB_STATUS status; DEV_INSTANCE_PTR new_instance_ptr, dev_instance_ptr, dev_instance_prev_ptr; PIPE_INIT_PARAM_STRUCT ctrl_pipe_init_params; USB_HOST_STATE_STRUCT_PTR usb_host_ptr; DEV_INSTANCE_PTR device_root = NULL; #ifdef __USB_OTG__ uint_32 state; #endif #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device attach device"); #endif usb_host_ptr = (USB_HOST_STATE_STRUCT_PTR)handle; /* Allocate new device instance */ new_instance_ptr = (DEV_INSTANCE_PTR) USB_mem_alloc_uncached(sizeof(DEV_INSTANCE)); if (new_instance_ptr == NULL) { #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device failed to malloc device handle"); #endif return USB_log_error(__FILE__,__LINE__, USBERR_GET_MEMORY_FAILED); } /* EndIf */ _mem_set_type(new_instance_ptr, MEM_TYPE_USB_HOST_STATE_STRUCT); USB_mem_zero(new_instance_ptr, sizeof(DEV_INSTANCE)); new_instance_ptr->host = handle; new_instance_ptr->speed = speed; new_instance_ptr->hub_no = hub_no; new_instance_ptr->port_no = port_no; new_instance_ptr->cfg_value = 0; /* We don't know yet what the device's default configuration is */ USB_lock(); /* Find unused address from 1 - 127 for this host */ dev_instance_ptr = usb_host_ptr->DEVICE_LIST_PTR; if ((dev_instance_ptr == NULL) || (dev_instance_ptr->address != 1)) { /* Insert at the beginning of list */ new_instance_ptr->address = 1; new_instance_ptr->next = dev_instance_ptr; usb_host_ptr->DEVICE_LIST_PTR = new_instance_ptr; } else { dev_instance_prev_ptr = dev_instance_ptr; /* Searching for a 'hole' in devices instance adresses */ while (dev_instance_ptr->address <= (dev_instance_prev_ptr->address + 1)) { new_instance_ptr->address = dev_instance_ptr->address; dev_instance_prev_ptr = dev_instance_ptr; dev_instance_ptr = dev_instance_ptr->next; if (dev_instance_ptr == NULL) break; } /* EndWhile */ if (new_instance_ptr->address >= 127) { /* If all 127 addresses used up, delete instance & bail out */ USB_unlock(); USB_mem_free((pointer)new_instance_ptr); #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device out of addresses"); #endif return USB_log_error(__FILE__,__LINE__, USBERR_ADDRESS_ALLOC_FAILED); } /* EndIf */ new_instance_ptr->address++; new_instance_ptr->next = dev_instance_ptr; dev_instance_prev_ptr->next = new_instance_ptr; }; USB_unlock(); /*-----------------------------------------------------------** ** Open control pipe, get first 8 bytes of device descriptor ** ** The host_ch9 routine internally sets the callback to ** ** usb_host_cntrl_transaction_done (in usb_host_ch9.c) ** ** where the action resumes on completion of the get. ** **-----------------------------------------------------------*/ ctrl_pipe_init_params = pipe_init_params_prototype; ctrl_pipe_init_params.G.DEV_INSTANCE = new_instance_ptr; ctrl_pipe_init_params.G.PIPETYPE = USB_CONTROL_PIPE; ctrl_pipe_init_params.G.SPEED = new_instance_ptr->speed; ctrl_pipe_init_params.G.HUB_DEVICE_ADDR = hub_no; ctrl_pipe_init_params.G.HUB_PORT_NUM = port_no; #ifdef __USB_OTG__ _usb_otg_get_status((pointer)usb_otg_state_struct_ptr, USB_OTG_STATE, &state); if (state < B_IDLE) { _usb_otg_set_status((pointer)usb_otg_state_struct_ptr, USB_OTG_A_BUS_REQ, TRUE); _usb_otg_set_status((pointer)usb_otg_state_struct_ptr, USB_OTG_B_CONN, TRUE); } else { _usb_otg_set_status((pointer)usb_otg_state_struct_ptr, USB_OTG_A_CONN, TRUE); } /* Endif */ #endif if (USB_OK != _usb_host_open_pipe(new_instance_ptr->host, &ctrl_pipe_init_params, &new_instance_ptr->control_pipe)) { USB_mem_free((pointer)new_instance_ptr); #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device open pipe failed"); #endif return USB_log_error(__FILE__,__LINE__, USBERR_PIPE_OPENED_FAILED); } /* Endif */ /* Set state to enter after transaction completion */ new_instance_ptr->state = DEVSTATE_DEVDESC8; status = _usb_host_ch9_get_descriptor((_usb_device_instance_handle)new_instance_ptr, USB_DESC_TYPE_DEV << 8, 0, 8, (uchar_ptr)&new_instance_ptr->dev_descriptor); if (status != USB_STATUS_TRANSFER_QUEUED) { new_instance_ptr->state = DEVSTATE_INITIAL; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device FAILED"); #endif return USB_log_error(__FILE__,__LINE__, USBERR_NO_DESCRIPTOR); } #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device SUCCESSFUL"); #endif return USB_OK; } /* EndBody */
void Main_Task ( uint_32 param ) { /* Body */ USB_STATUS status = USB_OK; _int_disable(); _int_install_unexpected_isr(); status = _usb_host_driver_install(HOST_CONTROLLER_NUMBER, (pointer)&_bsp_usb_host_callback_table); if (status) { _int_enable(); printf("ERROR: %ls", status); exit(1); } /* Endif */ status = _usb_host_init (HOST_CONTROLLER_NUMBER, /* Use value in header file */ MAX_FRAME_SIZE, /* Frame size per USB spec */ &host_handle); /* Returned pointer */ if (status != USB_OK) { _int_enable(); printf("\nUSB Host Initialization failed. STATUS: %x", status); fflush(stdout); goto Error_Cleanup; } /* Endif */ /* ** Since we are going to act as the host driver, register ** the driver information for wanted class/subclass/protocols */ status = _usb_host_driver_info_register(host_handle, DriverInfoTable); if (status != USB_OK) { _int_enable(); printf("\nDriver Registration failed. STATUS: %x", status); fflush(stdout); goto Error_Cleanup; } _int_enable(); pCmd = (COMMAND_OBJECT_PTR) USB_mem_alloc_zero(sizeof(COMMAND_OBJECT_STRUCT)); if (pCmd == NULL) { printf ("\nUnable to allocate Command Object"); fflush (stdout); goto Error_Cleanup; } pCmd->CBW_PTR = (CBW_STRUCT_PTR) USB_mem_alloc_zero(sizeof(CBW_STRUCT)); if (pCmd->CBW_PTR == NULL) { printf ("\nUnable to allocate Command Block Wrapper"); fflush (stdout); goto Error_Cleanup; } pCmd->CSW_PTR = (CSW_STRUCT_PTR) USB_mem_alloc_zero(sizeof(CSW_STRUCT)); if (pCmd->CSW_PTR == NULL) { printf ("\nUnable to allocate Command Status Wrapper"); fflush (stdout); goto Error_Cleanup; } buff_in = (uchar_ptr)USB_mem_alloc_uncached(0x400C); if (buff_in == NULL) { printf ("\nUnable to allocate Input Buffer"); fflush (stdout); goto Error_Cleanup; } _mem_zero(buff_in, 0x400C); buff_out = (uchar_ptr) USB_mem_alloc_uncached(0x0F); if (buff_out == NULL) { printf ("\nUnable to allocate Output Buffer"); fflush (stdout); goto Error_Cleanup; } _mem_zero(buff_out, 0x0F); printf("\nPlease insert Mass Storage Device.\n"); /*----------------------------------------------------** ** Infinite loop, waiting for events requiring action ** **----------------------------------------------------*/ for ( ; ; ) { switch ( mass_device.dev_state ) { case USB_DEVICE_IDLE: break ; case USB_DEVICE_ATTACHED: printf( "Mass Storage Device Attached\n" ); fflush(stdout); mass_device.dev_state = USB_DEVICE_SET_INTERFACE_STARTED; status = _usb_hostdev_select_interface(mass_device.dev_handle, mass_device.intf_handle, (pointer)&mass_device.class_intf); break ; case USB_DEVICE_SET_INTERFACE_STARTED: break; case USB_DEVICE_INTERFACED: usb_host_mass_test_storage(); mass_device.dev_state = USB_DEVICE_OTHER; break ; case USB_DEVICE_DETACHED: printf ( "\nMass Storage Device Detached\n" ); fflush(stdout); mass_device.dev_state = USB_DEVICE_IDLE; break; case USB_DEVICE_OTHER: break ; default: printf ( "Unknown Mass Storage Device State = %d\n",\ mass_device.dev_state ); fflush(stdout); break ; } /* Endswitch */ } /* Endfor */ Error_Cleanup: { if (pCmd != NULL) { if (pCmd->CSW_PTR != NULL) { USB_mem_free(pCmd->CSW_PTR); } if (pCmd->CBW_PTR != NULL) { USB_mem_free(pCmd->CBW_PTR); } USB_mem_free(pCmd); } if (buff_in != NULL) { USB_mem_free(buff_in); } if (buff_out != NULL) { USB_mem_free(buff_out); } if (host_handle != NULL) { _usb_host_shutdown (host_handle); } } } /* Endbody */
void Mouse_Task( uint_32 param ) { USB_STATUS status = USB_OK; _usb_pipe_handle pipe; TR_INIT_PARAM_STRUCT tr; HID_COMMAND_PTR hid_com; uchar_ptr buffer; _usb_host_handle mouse_host_handle = (_usb_host_handle) param; /*************************************************************************** ** Allocate memory for being able to send commands to HID class driver. Note ** that USB_mem_alloc_uncached() allocates aligned buffers on cache line boundry. ** This is required if program is running with data cache on system. ***************************************************************************/ hid_com = (HID_COMMAND_PTR) USB_mem_alloc_uncached(sizeof(HID_COMMAND)); /* event for USB callback signaling */ _lwevent_create(&USB_Mouse_Event, LWEVENT_AUTO_CLEAR); /* Allocate buffer to receive data from interrupt. It must be created on uncached heap, ** since some USB host controllers use DMA to access those buffers. */ buffer = USB_mem_alloc_uncached(HID_MOUSE_BUFFER_SIZE); if (!buffer) { printf("\nError allocating buffer!"); fflush(stdout); exit(1); } /* Endif */ printf("\nMQX USB HID Mouse Demo\nWaiting for USB Mouse to be attached...\n"); fflush(stdout); /* ** Infinite loop, waiting for events requiring action */ for ( ; ; ) { // Wait for insertion or removal event _lwevent_wait_ticks(&USB_Mouse_Event, USB_Mouse_Event_CTRL, FALSE, 0); switch ( mouse_hid_device.DEV_STATE ) { case USB_DEVICE_IDLE: break; case USB_DEVICE_ATTACHED: printf("\nMouse device attached\n"); fflush(stdout); mouse_hid_device.DEV_STATE = USB_DEVICE_SET_INTERFACE_STARTED; status = _usb_hostdev_select_interface(mouse_hid_device.DEV_HANDLE, mouse_hid_device.INTF_HANDLE, (pointer)&mouse_hid_device.CLASS_INTF); if (status != USB_OK) { printf("\nError in _usb_hostdev_select_interface: %x", status); fflush(stdout); exit(1); } /* Endif */ break; case USB_DEVICE_SET_INTERFACE_STARTED: break; case USB_DEVICE_INTERFACED: printf("Mouse interfaced, setting protocol...\n"); /* now we will set the USB Hid standard boot protocol */ mouse_hid_device.DEV_STATE = USB_DEVICE_SETTING_PROTOCOL; hid_com->CLASS_PTR = (CLASS_CALL_STRUCT_PTR)&mouse_hid_device.CLASS_INTF; hid_com->CALLBACK_FN = usb_host_hid_mouse_ctrl_callback; hid_com->CALLBACK_PARAM = 0; status = usb_class_hid_set_protocol(hid_com, USB_PROTOCOL_HID_MOUSE); if (status != USB_STATUS_TRANSFER_QUEUED) { printf("\nError in usb_class_hid_set_protocol: %x", status); fflush(stdout); } break; case USB_DEVICE_INUSE: pipe = _usb_hostdev_find_pipe_handle(mouse_hid_device.DEV_HANDLE, mouse_hid_device.INTF_HANDLE, USB_INTERRUPT_PIPE, USB_RECV); if(pipe){ printf("Mouse device ready, try to move the mouse\n"); while(1){ /****************************************************************** Initiate a transfer request on the interrupt pipe ******************************************************************/ usb_hostdev_tr_init(&tr, usb_host_hid_mouse_recv_callback, NULL); tr.RX_BUFFER = buffer; tr.RX_LENGTH = HID_MOUSE_BUFFER_SIZE; status = _usb_host_recv_data(mouse_host_handle, pipe, &tr); if (status != USB_STATUS_TRANSFER_QUEUED) { printf("\nError in _usb_host_recv_data: %x", status); fflush(stdout); } /* Wait untill we get the data from keyboard. */ _lwevent_wait_ticks(&USB_Mouse_Event, USB_Mouse_Event_CTRL | USB_Mouse_Event_DATA, FALSE, 0); /* if not detached in the meanwhile */ if(mouse_hid_device.DEV_STATE == USB_DEVICE_INUSE) { process_mouse_buffer((uchar *)buffer); } else { /* kick the outer loop again to handle the CTRL event */ _lwevent_set(&USB_Mouse_Event, USB_Mouse_Event_CTRL); break; } } } break; case USB_DEVICE_DETACHED: printf("Going to idle state\n"); mouse_hid_device.DEV_STATE = USB_DEVICE_IDLE; break; case USB_DEVICE_OTHER: break; default: printf("Unknown Mouse Device State = %d\n", mouse_hid_device.DEV_STATE); fflush(stdout); break; } /* Endswitch */ } /* Endfor */ } /* Endbody */
void Main_Task(uint_32 param) { USB_STATUS status = USB_OK; _usb_pipe_handle pipe; TR_INIT_PARAM_STRUCT tr; HID_COMMAND hid_com; uchar *buffer; printf("\n** MQX USB Keyboard To Mouse Demo **\n"); printf("\nDemo will allow you control mouse cursor on your PC using keyboard attached to TWR-SER2 board."); printf("\nThis demo requires TWR-SER2 card and correct BSP setting."); printf("\nSee FSL_MQX_getting_started.pdf chapter 7 for details."); fflush(stdout); MouseDev_Init(); /* Allocate buffer to receive data from interrupt. It must be created on uncached heap, ** since some USB host controllers use DMA to access those buffers. */ buffer = USB_mem_alloc_uncached(HID_BUFFER_SIZE); if (buffer == NULL) { printf("\nMemory allocation failed. STATUS: %x", status); fflush(stdout); _task_block(); } /* _usb_otg_init needs to be done with interrupts disabled */ _int_disable(); /* event for USB callback signaling */ _lwevent_create(&USB_Event, LWEVENT_AUTO_CLEAR); _int_install_unexpected_isr(); /* Register USB interface and its settings from BSP */ if (MQX_OK != _usb_host_driver_install(&_bsp_usb_host_khci0_if)) { printf("\n\nUSB Host Installation failed."); fflush(stdout); _task_block(); } /* ** It means that we are going to act like host, so we initialize the ** host stack. This call will allow USB system to allocate memory for ** data structures, it uses later (e.g pipes etc.). */ status = _usb_host_init(&_bsp_usb_host_khci0_if, &host_handle); if(status != USB_OK) { printf("\nUSB Host Initialization failed. STATUS: %x", status); fflush(stdout); _task_block(); } /* ** since we are going to act as the host driver, register the driver ** information for wanted class/subclass/protocols */ status = _usb_host_driver_info_register(host_handle, DriverInfoTable); if(status != USB_OK) { printf("\nDriver Registration failed. STATUS: %x", status); fflush(stdout); _task_block(); } _int_enable(); printf("\nHost initialization finished. Attach USB Keyboard to the board."); /* ** Infinite loop, waiting for events requiring action */ for(;;) { // Wait for insertion or removal event _lwevent_wait_ticks(&USB_Event, USB_EVENT_CTRL, FALSE, 0); switch (hid_device.DEV_STATE) { case USB_DEVICE_IDLE: break; case USB_DEVICE_ATTACHED: hid_device.DEV_STATE = USB_DEVICE_SET_INTERFACE_STARTED; status = _usb_hostdev_select_interface(hid_device.DEV_HANDLE, hid_device.INTF_HANDLE, (pointer) & hid_device.CLASS_INTF); if(status != USB_OK) { printf("\nError in _usb_hostdev_select_interface: %x", status); fflush(stdout); _task_block(); } break; case USB_DEVICE_SET_INTERFACE_STARTED: break; case USB_DEVICE_INTERFACED: printf("\nKeyboard device interfaced, setting protocol."); /* now we will set the USB Hid standard boot protocol */ hid_device.DEV_STATE = USB_DEVICE_SETTING_PROTOCOL; hid_com.CLASS_PTR = (CLASS_CALL_STRUCT_PTR) & hid_device.CLASS_INTF; hid_com.CALLBACK_FN = usb_host_hid_ctrl_callback; hid_com.CALLBACK_PARAM = 0; /* Force the keyboard to behave as in USB Hid class standard boot protocol */ status = usb_class_hid_set_protocol(&hid_com, USB_PROTOCOL_HID_KEYBOARD); if(status != USB_STATUS_TRANSFER_QUEUED) { printf("\nError in usb_class_hid_set_protocol: %x", status); fflush(stdout); } break; case USB_DEVICE_INUSE: pipe = _usb_hostdev_find_pipe_handle(hid_device.DEV_HANDLE, hid_device.INTF_HANDLE, USB_INTERRUPT_PIPE, USB_RECV); if(pipe) { printf("\n\nUse W, A, S or D to move the cursor.\nW = UP\nS = DOWN\nA = LEFT\nD = RIGHT\n"); while(1) { /****************************************************************** Initiate a transfer request on the interrupt pipe ******************************************************************/ usb_hostdev_tr_init(&tr, usb_host_hid_recv_callback, NULL); tr.G.RX_BUFFER = (uchar *) buffer; tr.G.RX_LENGTH = HID_BUFFER_SIZE; status = _usb_host_recv_data(host_handle, pipe, &tr); if(status != USB_STATUS_TRANSFER_QUEUED) { printf("\nError in _usb_host_recv_data: %x", status); fflush(stdout); } /* Wait untill we get the data from keyboard. */ _lwevent_wait_ticks(&USB_Event, USB_EVENT_CTRL | USB_EVENT_DATA, FALSE, 0); /* if not detached in the meanwhile */ if(hid_device.DEV_STATE == USB_DEVICE_INUSE) { process_kbd_buffer((uchar *)buffer); } else { /* kick the outer loop again to handle the CTRL event */ _lwevent_set(&USB_Event, USB_EVENT_CTRL); break; } /* Slight delay to be nice to other processes. (Note that keyboards have its own autorepeat delay typically much longer than one would expect. In case the user holds the key (without any other keys changed), the USB response from keyboard is delayed (typ by 500ms). This is why the USB host should handle autorepeat feature by itself (not done in this example) */ _time_delay(1); USB_HID_Periodic_Task(); //feed the USB device with the correct setup answers } } break; case USB_DEVICE_DETACHED: printf("Going to idle state\n"); hid_device.DEV_STATE = USB_DEVICE_IDLE; break; } } }