void usb_host_hid_ctrl_callback ( /* [IN] pointer to pipe */ _usb_pipe_handle pipe_handle, /* [IN] user-defined parameter */ pointer2 user_parm, /* [IN] buffer address */ uchar_ptr buffer, /* [IN] length of data transferred */ uint_32 buflen, /* [IN] status, hopefully USB_OK or USB_DONE */ uint_32 status ) { /* Body */ if (status == USBERR_ENDPOINT_STALLED) { printf("\nHID Set_Protocol Request BOOT is not supported!\n"); //fflush(stdout); } else if (status) { printf("\nHID Set_Protocol Request BOOT failed!: 0x%x ... END!\n", status); //fflush(stdout); exit(1); } /* Endif */ if(hid_device.DEV_STATE == USB_DEVICE_SETTING_PROTOCOL) hid_device.DEV_STATE = USB_DEVICE_INUSE; /* notify application that status has changed */ _usb_event_set(&USB_Event, USB_EVENT_CTRL); } /* Endbody */
static void usb_class_cdc_ctrl_acm_callback ( /* [IN] pointer to pipe */ _usb_pipe_handle pipe, /* [IN] user-defined parameter */ pointer param, /* [IN] buffer address */ pointer buffer, /* [IN] length of data transferred */ uint_32 len, /* [IN] status, hopefully USB_OK or USB_DONE */ uint_32 status ) { /* Body */ CLASS_CALL_STRUCT_PTR acm_instance = (CLASS_CALL_STRUCT_PTR) param; USB_ACM_CLASS_INTF_STRUCT_PTR if_ptr; UNUSED(pipe) UNUSED(buffer) UNUSED(len) UNUSED(status) if_ptr = (USB_ACM_CLASS_INTF_STRUCT_PTR) acm_instance->class_intf_handle; _usb_event_set(&if_ptr->acm_event, USB_ACM_CTRL_PIPE_FREE); /* mark we are not using interrupt pipe */ } /*EndBody */
static void usb_class_cdc_in_data_callback ( /* [IN] pointer to pipe */ _usb_pipe_handle pipe, /* [IN] user-defined parameter */ pointer param, /* [IN] buffer address */ pointer buffer, /* [IN] length of data transferred */ uint_32 len, /* [IN] status, hopefully USB_OK or USB_DONE */ uint_32 status ) { /* Body */ FILE_CDC_PTR fd_ptr = (FILE_CDC_PTR) param; CLASS_CALL_STRUCT_PTR data_instance = (CLASS_CALL_STRUCT_PTR) fd_ptr->DEV_PTR->DRIVER_INIT_PTR; USB_DATA_CLASS_INTF_STRUCT_PTR if_ptr; CLASS_CALL_STRUCT_PTR acm_instance; USB_ACM_CLASS_INTF_STRUCT_PTR acm_if_ptr; UNUSED(pipe) if_ptr = (USB_DATA_CLASS_INTF_STRUCT_PTR) data_instance->class_intf_handle; acm_instance = if_ptr->BOUND_CONTROL_INTERFACE; if ((acm_instance == NULL) || !usb_host_class_intf_validate(acm_instance)) len = 0; else if (((CDC_SERIAL_INIT_PTR) fd_ptr->FLAGS)->FLAGS & USB_UART_HW_FLOW) { acm_if_ptr = (USB_ACM_CLASS_INTF_STRUCT_PTR) acm_instance->class_intf_handle; /* check the state of DCD signal for HW flow control files */ if (!(acm_if_ptr->interrupt_buffer.bmStates & USB_ACM_STATE_RX_CARRIER)) len = 0; /* ignore all received bytes is DCD is not set */ /* check the state of DTR signal */ if (!(acm_if_ptr->ctrl_state.bmStates[1] & USB_ACM_LINE_STATE_DTR)) len = 0; /* ignore all sent bytes if DTR is not set */ } /* in the case we have less data than expected, status is not USB_OK, but buffer is not NULL */ if ((status != USB_OK) && (buffer == NULL)) /* if no data received */ len = 0; if (if_ptr->RX_BUFFER_DRV != NULL) if_ptr->RX_BUFFER_DRV += len; if_ptr->RX_READ = len; _usb_event_set(&if_ptr->data_event, USB_DATA_READ_COMPLETE); /* signal that we have completed transfer on input pipe */ } /*EndBody */
void usb_class_cdc_acm_init ( /* [IN] structure with USB pipe information on the interface */ PIPE_BUNDLE_STRUCT_PTR pbs_ptr, /* [IN] acm call struct pointer2 */ CLASS_CALL_STRUCT_PTR ccs_ptr ) { /* Body */ USB_ACM_CLASS_INTF_STRUCT_PTR acm_anchor = NULL; USB_ACM_CLASS_INTF_STRUCT_PTR if_ptr = ccs_ptr->class_intf_handle; USB_STATUS status; /* Make sure the device is still attached */ USB_lock(); status = usb_host_class_intf_init(pbs_ptr, if_ptr, &acm_anchor_abstract); if (status == USB_OK) { /* ** We generate a code_key based on the attached device. This is used to ** verify that the device has not been detached and replaced with another. */ ccs_ptr->code_key = 0; ccs_ptr->code_key = usb_host_class_intf_validate(ccs_ptr); if_ptr->CDC_G.IFNUM = ((INTERFACE_DESCRIPTOR_PTR)if_ptr->CDC_G.G.intf_handle)->bInterfaceNumber; if_ptr->interrupt_pipe = usb_hostdev_get_pipe_handle(pbs_ptr, USB_INTERRUPT_PIPE, 0); if (USB_OK != (status = _usb_event_init(&if_ptr->acm_event))) { status = USBERR_INIT_FAILED; } else { /* prepare events to be auto or manual */ //_lwevent_set_auto_clear(&if_ptr->acm_event, USB_ACM_CTRL_PIPE_FREE | USB_ACM_INT_PIPE_FREE); /* pre-set events */ _usb_event_set(&if_ptr->acm_event, USB_ACM_CTRL_PIPE_FREE | USB_ACM_INT_PIPE_FREE); } } /* Endif */ /* Signal that an error has occured by setting the "code_key" */ if (status) { ccs_ptr->code_key = 0; } /* Endif */ USB_unlock(); } /* Endbody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : IRQ_ISR * Returned Value : none * Comments : IRQ interrupt service routine * * *END*--------------------------------------------------------------------*/ void interrupt 64 IRQ_ISR(void) { if(USB_DEVICE_INTERFACED == audio_stream.DEV_STATE) { play = (boolean)(1 - play); /* play */ if (TRUE == play) { printf("Playing ...\r\n"); _usb_event_set(&USB_Event, USB_EVENT_RECEIVED_DATA); EnableTimer1Interrupt(); } /* stop */ else { printf("\nPaused.\n"); DisableTimer1Interrupt(); } } IRQ_SC |= IRQ_SC_IRQF_MASK | IRQ_SC_IRQACK_MASK; /* clear KBI interrupt */ }
void usb_host_hid_recv_callback ( /* [IN] pointer to pipe */ _usb_pipe_handle pipe_handle, /* [IN] user-defined parameter */ pointer2 user_parm, /* [IN] buffer address */ uchar_ptr buffer, /* [IN] length of data transferred */ uint_32 buflen, /* [IN] status, hopefully USB_OK or USB_DONE */ uint_32 status ) { /* Body */ /* notify application that data are available */ _usb_event_set(&USB_Event, USB_EVENT_DATA); }
USB_STATUS usb_class_cdc_set_acm_ctrl_state ( /* [IN] The communication device data instance structure */ CLASS_CALL_STRUCT_PTR ccs_ptr, /* [IN] DTR state to set */ uint_8 dtr, /* [IN] RTS state to set */ uint_8 rts ) { /* Body */ USB_DATA_CLASS_INTF_STRUCT_PTR if_data_ptr; USB_ACM_CLASS_INTF_STRUCT_PTR if_acm_ptr; CLASS_CALL_STRUCT_PTR acm_instance; USB_STATUS status = USBERR_NO_INTERFACE; USB_EVENT_STRUCT_PTR event; CDC_COMMAND cmd; USB_lock(); /* Validity checking: for data interface */ if (usb_host_class_intf_validate(ccs_ptr)) { if_data_ptr = (USB_DATA_CLASS_INTF_STRUCT_PTR)ccs_ptr->class_intf_handle; acm_instance = if_data_ptr->BOUND_CONTROL_INTERFACE; if (usb_host_class_intf_validate(acm_instance)) { if_acm_ptr = (USB_ACM_CLASS_INTF_STRUCT_PTR) if_data_ptr->BOUND_CONTROL_INTERFACE->class_intf_handle; if (if_acm_ptr->acm_desc->bmCapabilities & USB_ACM_CAP_LINE_CODING) { event = &if_acm_ptr->acm_event; USB_unlock(); /* we must wait until ctrl pipe is used */ #if !HIGH_SPEED_DEVICE while(USB_EVENT_NOT_SET == _usb_event_wait_ticks(event, USB_ACM_CTRL_PIPE_FREE | USB_ACM_DETACH, FALSE, 0)){ _usb_khci_task(); } #endif _usb_event_clear(event, USB_ACM_CTRL_PIPE_FREE | USB_ACM_DETACH); USB_lock(); if (usb_host_class_intf_validate(acm_instance)) { cmd.CLASS_PTR = ccs_ptr; cmd.CALLBACK_FN = (tr_callback)usb_class_cdc_ctrl_acm_callback; cmd.CALLBACK_PARAM = acm_instance; if_acm_ptr->ctrl_state.bmStates[0] = (uint_8)(dtr ? USB_ACM_LINE_STATE_DTR : 0); if_acm_ptr->ctrl_state.bmStates[0] |= rts ? USB_ACM_LINE_STATE_RTS : 0; status = usb_class_cdc_cntrl_common(&cmd, if_acm_ptr, REQ_TYPE_OUT | REQ_TYPE_CLASS | REQ_TYPE_INTERFACE, USB_CDC_SET_CTRL_LINE_STATE, * ((uint_16 *) &if_acm_ptr->ctrl_state), 0, NULL); } } else status = USBERR_INVALID_BMREQ_TYPE; } /* Endif */ } /* Endif */ USB_unlock(); #if !HIGH_SPEED_DEVICE while(USB_EVENT_NOT_SET == _usb_event_wait_ticks(event, USB_ACM_CTRL_PIPE_FREE | USB_ACM_DETACH, FALSE, 0)){ _usb_khci_task(); } #endif _usb_event_clear(event, USB_ACM_CTRL_PIPE_FREE | USB_ACM_DETACH); _usb_event_set(event, USB_ACM_CTRL_PIPE_FREE); return status; } /* Endbody */
USB_STATUS usb_class_cdc_get_acm_line_coding ( /* [IN] The communication device data instance structure */ CLASS_CALL_STRUCT_PTR ccs_ptr, /* [IN] Where to store coding */ USB_CDC_UART_CODING_PTR uart_coding_ptr ) { /* Body */ USB_DATA_CLASS_INTF_STRUCT_PTR if_data_ptr; USB_ACM_CLASS_INTF_STRUCT_PTR if_acm_ptr; CLASS_CALL_STRUCT_PTR acm_instance; USB_STATUS status = USBERR_NO_INTERFACE; USB_EVENT_STRUCT_PTR event; CDC_COMMAND cmd; USB_lock(); /* Validity checking: for data interface */ if (usb_host_class_intf_validate(ccs_ptr)) { if_data_ptr = (USB_DATA_CLASS_INTF_STRUCT_PTR)ccs_ptr->class_intf_handle; acm_instance = if_data_ptr->BOUND_CONTROL_INTERFACE; if (usb_host_class_intf_validate(if_data_ptr->BOUND_CONTROL_INTERFACE)) { if_acm_ptr = (USB_ACM_CLASS_INTF_STRUCT_PTR) if_data_ptr->BOUND_CONTROL_INTERFACE->class_intf_handle; if (if_acm_ptr->acm_desc->bmCapabilities & USB_ACM_CAP_LINE_CODING) { event = &if_acm_ptr->acm_event; USB_unlock(); /* we must wait until ctrl pipe is used */ #if !HIGH_SPEED_DEVICE while(USB_EVENT_NOT_SET == _usb_event_wait_ticks(event, USB_ACM_CTRL_PIPE_FREE | USB_ACM_DETACH, FALSE, 0)){ _usb_khci_task(); } #endif _usb_event_clear(event, USB_ACM_CTRL_PIPE_FREE | USB_ACM_DETACH); USB_lock(); if (usb_host_class_intf_validate(acm_instance)) { cmd.CLASS_PTR = ccs_ptr; cmd.CALLBACK_FN = (tr_callback)usb_class_cdc_ctrl_acm_callback; cmd.CALLBACK_PARAM = acm_instance; status = usb_class_cdc_cntrl_common(&cmd, if_acm_ptr, REQ_TYPE_IN | REQ_TYPE_CLASS | REQ_TYPE_INTERFACE, USB_CDC_GET_LINE_CODING, 0, 7 /* sizeof(USB_CDC_UART_CODING)*/, (uchar_ptr)uart_coding_ptr); } } else status = USBERR_INVALID_BMREQ_TYPE; } /* Endif */ } /* Endif */ USB_unlock(); #if !HIGH_SPEED_DEVICE while(USB_EVENT_NOT_SET == _usb_event_wait_ticks(event, USB_ACM_CTRL_PIPE_FREE | USB_ACM_DETACH, FALSE, 0)){ _usb_khci_task(); } #endif _usb_event_clear(event, USB_ACM_CTRL_PIPE_FREE | USB_ACM_DETACH); _usb_event_set(event, USB_ACM_CTRL_PIPE_FREE); return status; } /* Endbody */
void usb_host_hid_mouse_event ( /* [IN] pointer to device instance */ _usb_device_instance_handle dev_handle, /* [IN] pointer to interface descriptor */ _usb_interface_descriptor_handle intf_handle, /* [IN] code number for event causing callback */ uint_32 event_code ) { /* Body */ INTERFACE_DESCRIPTOR_PTR intf_ptr = (INTERFACE_DESCRIPTOR_PTR)intf_handle; switch (event_code) { case USB_ATTACH_EVENT: printf("----- Attach Event -----\n"); /* Drop through into attach, same processing */ case USB_CONFIG_EVENT: printf("State = %d", hid_device.DEV_STATE); printf(" Class = %d", intf_ptr->bInterfaceClass); printf(" SubClass = %d", intf_ptr->bInterfaceSubClass); printf(" Protocol = %d\n", intf_ptr->bInterfaceProtocol); ////fflush(stdout); if (hid_device.DEV_STATE == USB_DEVICE_IDLE) { hid_device.DEV_HANDLE = dev_handle; hid_device.INTF_HANDLE = intf_handle; hid_device.DEV_STATE = USB_DEVICE_ATTACHED; } else { printf("HID device already attached - DEV_STATE = %d\n", hid_device.DEV_STATE); ////fflush(stdout); } /* Endif */ break; case USB_INTF_EVENT: printf("----- Interfaced Event -----\n"); hid_device.DEV_STATE = USB_DEVICE_INTERFACED; break ; case USB_DETACH_EVENT: /* Use only the interface with desired protocol */ printf("----- Detach Event -----\n"); printf("State = %d", hid_device.DEV_STATE); printf(" Class = %d", intf_ptr->bInterfaceClass); printf(" SubClass = %d", intf_ptr->bInterfaceSubClass); printf(" Protocol = %d\n", intf_ptr->bInterfaceProtocol); ////fflush(stdout); hid_device.DEV_HANDLE = NULL; hid_device.INTF_HANDLE = NULL; hid_device.DEV_STATE = USB_DEVICE_DETACHED; break; default: printf("HID Device state = %d??\n", hid_device.DEV_STATE); ////fflush(stdout); hid_device.DEV_STATE = USB_DEVICE_IDLE; break; } /* EndSwitch */ /* notify application that status has changed */ _usb_event_set(&USB_Event, USB_EVENT_CTRL); } /* Endbody */
void usb_class_cdc_data_init ( /* [IN] structure with USB pipe information on the interface */ PIPE_BUNDLE_STRUCT_PTR pbs_ptr, /* [IN] acm call struct pointer */ CLASS_CALL_STRUCT_PTR ccs_ptr ) { /* Body */ USB_DATA_CLASS_INTF_STRUCT_PTR if_ptr = ccs_ptr->class_intf_handle; ENDPOINT_DESCRIPTOR_PTR in_endpt, out_endpt; USB_STATUS status; /* Make sure the device is still attached */ USB_lock(); status = usb_host_class_intf_init(pbs_ptr, if_ptr, &data_anchor_abstract); if (status == USB_OK) { /* ** We generate a code_key based on the attached device. This is used to ** verify that the device has not been detached and replaced with another. */ ccs_ptr->code_key = 0; ccs_ptr->code_key = usb_host_class_intf_validate(ccs_ptr); if_ptr->CDC_G.IFNUM = ((INTERFACE_DESCRIPTOR_PTR)if_ptr->CDC_G.G.intf_handle)->bInterfaceNumber; if_ptr->in_pipe = usb_hostdev_get_pipe_handle(pbs_ptr, USB_BULK_PIPE, USB_RECV); if_ptr->out_pipe = usb_hostdev_get_pipe_handle(pbs_ptr, USB_BULK_PIPE, USB_SEND); if ((if_ptr->in_pipe == NULL) && (if_ptr->out_pipe == NULL)) status = USBERR_OPEN_PIPE_FAILED; else if (USB_OK != (status = _usb_event_init(&if_ptr->data_event))) status = USBERR_INIT_FAILED; else { /* prepare events to be auto or manual */ //_lwevent_set_auto_clear(&if_ptr->data_event, USB_DATA_READ_PIPE_FREE | USB_DATA_SEND_PIPE_FREE); /* pre-set events */ _usb_event_set(&if_ptr->data_event, USB_DATA_READ_PIPE_FREE | USB_DATA_SEND_PIPE_FREE); if (if_ptr->out_pipe) { /* Don't use host - predefined constant for NAK_COUNT... ** NOTE!!! ** This hack is not very clean. We need to maximize number of retries to minimize the time of ** transaction (minimize task's time while waiting for 1 transaction to be done (with or without data)) ** The time depends on user expecatation of the read() latency, on the delay between 2 NAKs and on number ** of NAKs to be performed. ** The workaround is to limit amount of retries for the pipe maximally to 3. ** Number 3 is hard-coded here for now. */ if (((PIPE_DESCRIPTOR_STRUCT_PTR) if_ptr->in_pipe)->NAK_COUNT > 3) ((PIPE_DESCRIPTOR_STRUCT_PTR) if_ptr->in_pipe)->NAK_COUNT = 3; /* don't use host - predefined constant */ } if (if_ptr->in_pipe) { /* The same as for OUT pipe applies here */ if (((PIPE_DESCRIPTOR_STRUCT_PTR) if_ptr->out_pipe)->NAK_COUNT > 3) ((PIPE_DESCRIPTOR_STRUCT_PTR) if_ptr->out_pipe)->NAK_COUNT = 3; /* don't use host - predefined constant */ /* initialize buffer */ /* size of buffer equals to the size of endpoint data size */ if_ptr->RX_BUFFER_SIZE = ((PIPE_INIT_PARAM_STRUCT_PTR) (if_ptr->in_pipe))->MAX_PACKET_SIZE; if (NULL == (if_ptr->RX_BUFFER = USB_mem_alloc_zero(if_ptr->RX_BUFFER_SIZE))) { status = USBERR_ALLOC; } else { /* initialize members */ if_ptr->RX_BUFFER_APP = if_ptr->RX_BUFFER_DRV = if_ptr->RX_BUFFER; } } } } /* Endif */ /* Signal that an error has occured by setting the "code_key" */ if (status) { ccs_ptr->code_key = 0; } /* Endif */ USB_unlock(); } /* Endbody */
void usb_host_cdc_data_event ( /* [IN] pointer to device instance */ _usb_device_instance_handle dev_handle, /* [IN] pointer to interface descriptor */ _usb_interface_descriptor_handle intf_handle, /* [IN] code number for event causing callback */ uint_32 event_code ) { /* Body */ INTERFACE_DESCRIPTOR_PTR intf_ptr = (INTERFACE_DESCRIPTOR_PTR)intf_handle; DATA_DEVICE_STRUCT_PTR data_device; fflush(stdout); switch (event_code) { case USB_CONFIG_EVENT: /* Drop through into attach, same processing */ case USB_ATTACH_EVENT: { /* This data interface could be controlled by some control interface, * which could be already initialized (or not). We have to find * that interface. Then we need to bind this interface with * found control interface. */ INTERFACE_DESCRIPTOR_PTR if_desc; if (USB_OK != usb_class_cdc_get_ctrl_descriptor(dev_handle, intf_handle, &if_desc)) break; /* interface descriptor found, so we can allocate new data device */ if (NULL == (data_device = USB_mem_alloc_zero(sizeof(DATA_DEVICE_STRUCT)))) break; /* initializes interface members and selects it */ if (USB_OK != _usb_hostdev_select_interface(dev_handle, intf_handle, (pointer)&data_device->CLASS_INTF)) { free(data_device); break; } /* binds this data interface with its control interface, if possible */ if (USB_OK != usb_class_cdc_bind_acm_interface((pointer)&data_device->CLASS_INTF, if_desc)) { free(data_device); break; } #if 0 /* << EST */ printf("----- CDC data interface attach event -----\n"); fflush(stdout); printf("State = attached"); printf(" Class = %%d", intf_ptr->bInterfaceClass); printf(" SubClass = %%d", intf_ptr->bInterfaceSubClass); printf(" Protocol = %%d\n", intf_ptr->bInterfaceProtocol); fflush(stdout); #endif check_open = 0; break; } case USB_INTF_EVENT: { CLASS_CALL_STRUCT_PTR data_parser; //USB_CDC_UART_CODING uart_coding; #if 0 /* << EST */ fflush(stdout); #endif if (NULL == (data_parser = usb_class_cdc_get_data_interface(intf_handle))) break; if (USB_OK == usb_class_cdc_install_driver(data_parser, device_name)) { if (((USB_DATA_CLASS_INTF_STRUCT_PTR) (data_parser->class_intf_handle))->BOUND_CONTROL_INTERFACE != NULL) { if (reg_device == 0) { reg_device = dev_handle; _usb_event_set(&device_registered, 0x01); } } #if 0 /* << EST */ printf("----- Device installed -----\n"); #endif } #if 0 /* << EST */ printf("----- CDC data interface selected -----\n"); #endif break; } case USB_DETACH_EVENT: { CLASS_CALL_STRUCT_PTR data_parser; USB_DATA_CLASS_INTF_STRUCT_PTR if_ptr; if (NULL == (data_parser = usb_class_cdc_get_data_interface(intf_handle))) break; if_ptr = (USB_DATA_CLASS_INTF_STRUCT_PTR) data_parser->class_intf_handle; if (if_ptr->in_pipe != NULL) _usb_event_set(&if_ptr->data_event, USB_DATA_DETACH); /* mark we are not using input pipe */ /* Allow tasks waiting for data to be finished... ** This does have sense only if this task will not be active ** or scheduler switches to another task. ** For simplification, we dont use any semaphore to indicate that ** all tasks have finished its job with device. Instead, we have just ** informed them that device is detached and we rely on USB stack layer ** that it checking if the device is available returns false. ** The code that would synchronize tasks to be finished would look like: ** ** _lwsem_wait(if_ptr->device_using_tasks); */ /* unbind data interface */ if (USB_OK != usb_class_cdc_unbind_acm_interface(data_parser)) break; //if (USB_OK != usb_class_cdc_uninstall_driver(data_parser)) // break; if (if_ptr->in_pipe != NULL) { free(if_ptr->RX_BUFFER); } if (reg_device == dev_handle) { reg_device = 0; _usb_event_clear(&device_registered, 0x01); } #if 0 /* << EST */ printf("----- CDC data interface detach Event -----\n"); fflush(stdout); printf("State = detached"); printf(" Class = %%d", intf_ptr->bInterfaceClass); printf(" SubClass = %%d", intf_ptr->bInterfaceSubClass); printf(" Protocol = %%d\n", intf_ptr->bInterfaceProtocol); fflush(stdout); #endif break; } default: #if 0 /* << EST */ printf("CDC device: unknown data event\n"); fflush(stdout); #endif break; } /* EndSwitch */ } /* Endbody */
void usb_host_cdc_acm_event ( /* [IN] pointer to device instance */ _usb_device_instance_handle dev_handle, /* [IN] pointer to interface descriptor */ _usb_interface_descriptor_handle intf_handle, /* [IN] code number for event causing callback */ uint_32 event_code ) { /* Body */ INTERFACE_DESCRIPTOR_PTR intf_ptr = (INTERFACE_DESCRIPTOR_PTR)intf_handle; ACM_DEVICE_STRUCT_PTR acm_device; #if 0 /* << EST */ fflush(stdout); #endif switch (event_code) { case USB_CONFIG_EVENT: /* Drop through into attach, same processing */ case USB_ATTACH_EVENT: { USB_CDC_DESC_ACM_PTR acm_desc = NULL; USB_CDC_DESC_CM_PTR cm_desc = NULL; USB_CDC_DESC_HEADER_PTR header_desc = NULL; USB_CDC_DESC_UNION_PTR union_desc = NULL; int_32 external_data = 0; /* finds all the descriptors in the configuration */ if (USB_OK != usb_class_cdc_get_acm_descriptors(dev_handle, intf_handle, &acm_desc, &cm_desc, &header_desc, &union_desc)) break; /* we can allocate new acm device */ if (NULL == (acm_device = USB_mem_alloc_zero(sizeof(ACM_DEVICE_STRUCT)))) break; /* initialize new interface members and select this interface */ if (USB_OK != _usb_hostdev_select_interface(dev_handle, intf_handle, (pointer)&acm_device->CLASS_INTF)) { free(acm_device); break; } /* set all info got from descriptors to the class interface struct */ usb_class_cdc_set_acm_descriptors((pointer)&acm_device->CLASS_INTF, acm_desc, cm_desc, header_desc, union_desc); /* link all already registered data interfaces to this ACM control, if needed */ if (USB_OK != usb_class_cdc_bind_data_interfaces(dev_handle, (pointer)&acm_device->CLASS_INTF)) { free(acm_device); break; } #if 0 /* << EST */ printf("----- CDC control interface attach Event -----\n"); fflush(stdout); printf("State = attached"); printf(" Class = %%d", intf_ptr->bInterfaceClass); printf(" SubClass = %%d", intf_ptr->bInterfaceSubClass); printf(" Protocol = %%d\n", intf_ptr->bInterfaceProtocol); fflush(stdout); #endif check_open = 0; break; } case USB_INTF_EVENT: { CLASS_CALL_STRUCT_PTR acm_parser; USB_STATUS status; if (NULL == (acm_parser = usb_class_cdc_get_ctrl_interface(intf_handle))) break; status = usb_class_cdc_init_ipipe(acm_parser); if ((status != USB_OK) && (status != USBERR_OPEN_PIPE_FAILED)) break; #if 0 /* << EST */ printf("----- CDC control interface selected -----\n"); #endif break; } case USB_DETACH_EVENT: { CLASS_CALL_STRUCT_PTR acm_parser; USB_ACM_CLASS_INTF_STRUCT_PTR if_ptr; if (NULL == (acm_parser = usb_class_cdc_get_ctrl_interface(intf_handle))) break; if_ptr = (USB_ACM_CLASS_INTF_STRUCT_PTR) acm_parser->class_intf_handle; _usb_event_set(&if_ptr->acm_event, USB_ACM_DETACH); /* mark we are not using input pipe */ /* Allow tasks waiting for acm to be finished... ** This does have sense only if this task will not be active ** or scheduler switches to another task. ** For simplification, we dont use any semaphore to indicate that ** all tasks have finished its job with device. Instead, we have just ** informed them that device is detached and we rely on USB stack layer ** that it checking if the device is available returns false. ** The code that would synchronize tasks to be finished would look like: ** ** _lwsem_wait(if_ptr->device_using_tasks); */ usb_class_cdc_unbind_data_interfaces(acm_parser); USB_unlock(); free(acm_parser); /* Use only the interface with desired protocol */ #if 0 /* << EST */ printf("----- CDC control interface detach event -----\n"); fflush(stdout); printf("State = detached"); printf(" Class = %%d", intf_ptr->bInterfaceClass); printf(" SubClass = %%d", intf_ptr->bInterfaceSubClass); printf(" Protocol = %%d\n", intf_ptr->bInterfaceProtocol); fflush(stdout); #endif break; } break; default: #if 0 /* << EST */ printf("CDC device: unknown control event\n"); fflush(stdout); #endif break; } /* EndSwitch */ } /* Endbody */