/*FUNCTION*---------------------------------------------------------------- * * Function Name : _usb_hostdev_cntrl_request * Returned Value : USB_OK, or error status * Comments : * Function to process class- or vendor-specific control pipe device * requests. * *END*--------------------------------------------------------------------*/ USB_STATUS _usb_hostdev_cntrl_request ( /* usb device */ _usb_device_instance_handle dev_handle, /* Device Request to send */ USB_SETUP_PTR devreq, /* buffer to send/receive */ uchar_ptr buff_ptr, /* callback upon completion */ tr_callback callback, /* [IN] the parameter to pass back to the callback function */ pointer callback_param ) { /* Body */ DEV_INSTANCE_PTR dev_ptr; _usb_pipe_handle pipe_handle; TR_INIT_PARAM_STRUCT tr; USB_STATUS error = USB_OK; /* Verify that device handle is valid */ USB_lock(); error = usb_hostdev_validate(dev_handle); if (error != USB_OK) { USB_unlock(); return USBERR_DEVICE_NOT_FOUND; } /* Endif */ dev_ptr = (DEV_INSTANCE_PTR)dev_handle; if (dev_ptr->state < DEVSTATE_ENUM_OK) { USB_unlock(); return USBERR_DEVICE_NOT_FOUND; } /* Endif */ pipe_handle = dev_ptr->control_pipe; usb_hostdev_tr_init(&tr, callback, callback_param); /* Set TR buffer length as required */ if ((REQ_TYPE_IN & devreq->BMREQUESTTYPE) != 0) { tr.RX_BUFFER = buff_ptr; tr.RX_LENGTH = utoh16(devreq->WLENGTH); } else { tr.TX_BUFFER = buff_ptr; tr.TX_LENGTH = utoh16(devreq->WLENGTH); } /* EndIf */ tr.DEV_REQ_PTR = (uchar_ptr)devreq; error = _usb_host_send_setup(dev_ptr->host, pipe_handle, &tr); USB_unlock(); return error; } /* EndBody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_host_ch9_dev_req * Returned Value : USB_OK, or error status * Comments : * Function to process standard device requests in Chapter 9. * See Table 9-3 p. 250 of USB 2.0 specification. * This code does minimal error checking, on the assumption * that it is called only from wrappers in this file. * It is presumed that this function is called with USB interrupts disabled * *END*--------------------------------------------------------------------*/ static USB_STATUS usb_host_ch9_dev_req ( /* usb device */ _usb_device_instance_handle dev_handle, /* Device Request to send */ USB_SETUP_PTR devreq_ptr, /* buffer to send/receive */ uchar_ptr buff_ptr ) { /* Body */ DEV_INSTANCE_PTR dev_ptr; _usb_pipe_handle pipe_handle; TR_INIT_PARAM_STRUCT tr; USB_STATUS error; /* Verify that device handle is valid */ error = usb_hostdev_validate(dev_handle); if (error != USB_OK) { return USBERR_DEVICE_NOT_FOUND; } /* Endif */ dev_ptr = (DEV_INSTANCE_PTR)dev_handle; pipe_handle = dev_ptr->control_pipe; /* Initialize the TR with TR index and default control callback ** function if there is one registered */ usb_hostdev_tr_init(&tr, dev_ptr->control_callback, dev_ptr->control_callback_param); /* Set buffer length if required */ switch (devreq_ptr->BREQUEST) { case REQ_SET_DESCRIPTOR: tr.TX_BUFFER = buff_ptr; tr.TX_LENGTH = utoh16(devreq_ptr->WLENGTH); break; case REQ_GET_CONFIGURATION: case REQ_GET_DESCRIPTOR: case REQ_GET_INTERFACE: case REQ_GET_STATUS: case REQ_SYNCH_FRAME: tr.RX_BUFFER = buff_ptr; tr.RX_LENGTH = utoh16(devreq_ptr->WLENGTH); break; } /* EndSwitch */ tr.DEV_REQ_PTR = (uchar_ptr)(devreq_ptr); if ((dev_ptr->state < DEVSTATE_ENUM_OK) || (tr.CALLBACK == NULL)) { tr.CALLBACK = usb_host_cntrl_transaction_done; tr.CALLBACK_PARAM = NULL; } /* Endif */ error = _usb_host_send_setup(dev_ptr->host, pipe_handle, &tr); return error; } /* EndBody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_host_cntrl_transaction_done * Returned Value : none * Comments : * Callback function to process transaction-done events * State machine for enumeration/subsequent transactions * Between states, the 8-byte buffer in device_instance * is used to save the first part of the configuration. * Pointer desc in various flavors (uchar_ptr, cfig_ptr) * is used to parse this buffer in various ways. * *END*--------------------------------------------------------------------*/ static void usb_host_cntrl_transaction_done ( /* [IN] the pipe handle */ _usb_pipe_handle handle, /* [IN] The user parameter */ pointer user_parm, /* [IN] the buffer */ uchar_ptr buffer, /* [IN] The length of the transfer */ uint_32 length, /* [IN] status of the transfer */ uint_32 status ) { /* Body */ USB_HOST_STATE_STRUCT_PTR usb_host_ptr; PIPE_DESCRIPTOR_STRUCT_PTR pipe_ptr = (PIPE_DESCRIPTOR_STRUCT_PTR)handle; DEV_INSTANCE_PTR dev_inst_ptr = (DEV_INSTANCE_PTR)pipe_ptr->DEV_INSTANCE; DESCRIPTOR_UNION desc; pointer temp = NULL; uint_32 config_size; usb_host_ptr = (USB_HOST_STATE_STRUCT_PTR)dev_inst_ptr->host; /*----------------------------------------------------** ** Enumeration state machine -- cases are named after ** ** the just-completed transactions. ** **----------------------------------------------------*/ switch (dev_inst_ptr->state) { case DEVSTATE_INITIAL: /* initial device state */ break; case DEVSTATE_DEVDESC8: /* device descriptor [0..7]*/ /* We must have received the first 8 bytes in ** dev_inst_ptr->dev_descriptor which contains the ** max packet size for this control endpoint */ pipe_ptr->MAX_PACKET_SIZE = dev_inst_ptr->dev_descriptor.bMaxPacketSize; /* Notify device driver of MaxPacketSize0 for this device */ status = _usb_host_update_max_packet_size_call_interface (usb_host_ptr, pipe_ptr); if (status != USB_OK) { dev_inst_ptr->state = DEVSTATE_INITIAL; break; } else { dev_inst_ptr->state = DEVSTATE_ADDR_SET; } /* Now set the address that we assigned when we initialized ** the device instance struct for this device */ status = _usb_host_ch9_set_address((pointer)dev_inst_ptr); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; break; } break; case DEVSTATE_ADDR_SET: /* address set */ pipe_ptr->DEVICE_ADDRESS = dev_inst_ptr->address; /* Notify device driver of USB device's new address */ status = _usb_host_update_device_address_call_interface (usb_host_ptr, pipe_ptr); if (status != USB_OK) { dev_inst_ptr->state = DEVSTATE_INITIAL; break; } dev_inst_ptr->state = DEVSTATE_DEV_DESC; /* Now get the full descriptor */ status = _usb_host_ch9_get_descriptor((pointer)dev_inst_ptr, USB_DESC_TYPE_DEV << 8, 0, USB_DESC_LEN_DEV, (uchar_ptr)&dev_inst_ptr->dev_descriptor); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; break; } break; case DEVSTATE_DEV_DESC: /* full device descriptor received */ /* Now lets get the first 9 bytes of the configuration ** descriptor */ desc.pntr = &dev_inst_ptr->buffer; dev_inst_ptr->state = DEVSTATE_GET_CFG9; status = _usb_host_ch9_get_descriptor((pointer)dev_inst_ptr, USB_DESC_TYPE_CFG << 8, 0, sizeof(dev_inst_ptr->buffer), desc.bufr); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; break; } break; case DEVSTATE_GET_CFG9: /* Read 9 bytes of config descriptor */ dev_inst_ptr->state = DEVSTATE_SET_CFG; /* Now select the configuration as specified in the ** descriptor */ desc.cfig = (CONFIGURATION_DESCRIPTOR_PTR)dev_inst_ptr->buffer; config_size = utoh16(desc.cfig->wTotalLength); desc.pntr = &dev_inst_ptr->buffer; if (USB_OK != usb_dev_list_get_memory(dev_inst_ptr, config_size, USB_MEMTYPE_CONFIG, (pointer _PTR_)&desc)) { return; } desc.word += MEM_HEADER_LEN; /* step past header */ dev_inst_ptr->state = DEVSTATE_SET_CFG; #ifdef OTG_BUILD //the device has to be attached directly(no intervening hub between the Host and the B device) if(dev_inst_ptr->next == (DEV_INSTANCE_PTR)NULL) { dev_inst_ptr->state = DEVSTATE_CHK_OTG; } #endif /* We can only read one config descriptor at a time */ status = _usb_host_ch9_get_descriptor((pointer)dev_inst_ptr, USB_DESC_TYPE_CFG << 8, 0, (uint_16)config_size, desc.bufr); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; break; } break; #ifdef OTG_BUILD case DEVSTATE_CHK_OTG: /* Point to the memory owned by this device */ desc.pntr = &dev_inst_ptr->memlist->payload; /* We will always start with config desc so update the search pointer */ config_size = utoh16(desc.cfig->wTotalLength); config_size -= desc.cfig->bLength; desc.word += desc.cfig->bLength; while (config_size) { if (desc.otg->bDescriptorType == USB_DESC_TYPE_OTG) { /* Found the OTG descriptor */ break; } /* Endif */ config_size -= desc.intf->bLength; desc.word += desc.intf->bLength; } /* EndWhile */ /* Check for an OTG descriptor */ dev_inst_ptr->state = DEVSTATE_SET_CFG; if (config_size && (desc.otg->bDescriptorType == USB_DESC_TYPE_OTG)) { if(_usb_otg_get_otg_attribute( dev_inst_ptr , desc.otg->bmAttributes) == USB_OK ) { if( _usb_otg_set_feature_required(dev_inst_ptr) ) { status = _usb_host_ch9_set_feature(dev_inst_ptr, 0, 0, OTG_A_HNP_SUPPORT); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; } else { dev_inst_ptr->state = DEVSTATE_SET_HNP; } break; } } } /* Endif */ /* Fall through */ #endif case DEVSTATE_SET_CFG: /* config descriptor [0..8] */ /* Point to the memory owned by this device */ desc.pntr = &dev_inst_ptr->memlist->payload; dev_inst_ptr->state = DEVSTATE_CFG_READ; status = _usb_host_ch9_set_configuration(dev_inst_ptr, desc.cfig->bConfigurationValue); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; break; } break; #ifdef OTG_BUILD case DEVSTATE_SET_HNP: dev_inst_ptr->state = DEVSTATE_SET_CFG; status = _usb_host_ch9_set_feature(dev_inst_ptr, 0, 0, OTG_B_HNP_ENABLE); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; } else { _usb_otg_a_set_b_hnp_en(dev_inst_ptr, TRUE); } break; #endif case DEVSTATE_CFG_READ: /* full config desc. read in */ dev_inst_ptr->state = DEVSTATE_APP_CALL; /* Scan the configuration descriptor to find out the total ** number of interfaces available. This will be the upper ** bound for searching through the interface descriptors' ** array */ dev_inst_ptr->num_of_interfaces = 0; /* Point to the memory owned by this device */ desc.pntr = &dev_inst_ptr->memlist->payload; /* We will always start with config desc so update the search pointer */ config_size = utoh16(desc.cfig->wTotalLength); config_size -= desc.cfig->bLength; desc.word += desc.cfig->bLength; while (config_size) { if (desc.intf->bDescriptorType == USB_DESC_TYPE_IF) { /* Found an interface */ dev_inst_ptr->num_of_interfaces++; } /* Endif */ /* EAI - if desc.intf->bLength this while loop never exits!!!! */ if (desc.intf->bLength) { config_size -= desc.intf->bLength; desc.word += desc.intf->bLength; } else { /* Not sure what proper error recovery is yet. */ break; } } /* EndWhile */ /* Don't select an interface here. The device driver will ** select the interface */ case DEVSTATE_APP_CALL: /* full config desc. read in */ dev_inst_ptr->state = DEVSTATE_SET_INTF; if (dev_inst_ptr->new_config != 0) { /* We have just read a new configuration descriptor */ dev_inst_ptr->new_config = 0; usb_hostdev_attach_detach(dev_inst_ptr, USB_CONFIG_EVENT); } else { usb_hostdev_attach_detach(dev_inst_ptr, USB_ATTACH_EVENT); } /* EndIf */ break; case DEVSTATE_SET_INTF: /* Select interface done */ dev_inst_ptr->state = DEVSTATE_ENUM_OK; usb_hostdev_attach_detach(dev_inst_ptr, USB_INTF_EVENT); break; default: dev_inst_ptr->state = DEVSTATE_ENUM_OK; case DEVSTATE_ENUM_OK: /* enumeration complete */ if ((dev_inst_ptr->control_callback != NULL)) dev_inst_ptr->control_callback (handle, user_parm, buffer, length, status); break; } /* EndSwitch */ } /* EndBody */
USB_STATUS usb_class_cdc_get_acm_descriptors ( /* [IN] pointer to device instance */ _usb_device_instance_handle dev_handle, /* [IN] pointer to interface descriptor */ _usb_interface_descriptor_handle intf_handle, USB_CDC_DESC_ACM_PTR _PTR_ acm_desc, USB_CDC_DESC_CM_PTR _PTR_ cm_desc, USB_CDC_DESC_HEADER_PTR _PTR_ header_desc, USB_CDC_DESC_UNION_PTR _PTR_ union_desc ) { INTERFACE_DESCRIPTOR_PTR intf_ptr = (INTERFACE_DESCRIPTOR_PTR)intf_handle; USB_STATUS status; int_32 i; USB_CDC_FUNC_DESC_PTR fd; INTERFACE_DESCRIPTOR_PTR if_desc; status = USB_OK; /* collect all interface functional descriptors */ for (i = 0; ; i++) { if (USB_OK != _usb_hostdev_get_descriptor( dev_handle, intf_handle, USB_DESC_TYPE_CS_INTERFACE, /* Functional descriptor for interface */ i, /* Index of descriptor */ intf_ptr->bAlternateSetting, /* Index of interface alternate */ &fd)) { /* Here we can check capabilities from functional descriptors */ /* But for now, nothing is checked */ if (union_desc == NULL) status = USBERR_INIT_FAILED; break; } switch (fd->header.bDescriptorSubtype) { case USB_DESC_SUBTYPE_CS_HEADER: *header_desc = fd; if (utoh16((*header_desc)->bcdCDC) > 0x0110) status = USBERR_INIT_FAILED; break; case USB_DESC_SUBTYPE_CS_UNION: /* Check if this union descriptor describes master for this interface */ if (fd->uni.bMasterInterface == intf_ptr->bInterfaceNumber) { /* Check if another union descriptor has not been already assigned */ if (*union_desc == NULL) *union_desc = fd; else status = USBERR_INIT_FAILED; } break; case USB_DESC_SUBTYPE_CS_ACM: *acm_desc = fd; break; case USB_DESC_SUBTYPE_CS_CM: *cm_desc = fd; break; } if (status != USB_OK) break; } return status; }