📄 pdc_bus.c
字号:
}} /* End of pdc_bus_set_interface() */void pdc_bus_get_status(__u8 *command){ unsigned char reply[4]; __u8 bmRequestType = command[0]; pdc_pipe_handle_t handle; __u8 reply_len = 2; if((bus_dev->state < PDC_BUS_ADDRESSED) || !(command[0]&PDC_REQTYPE_DIR_MASK)) { /* You are not supposed to receive this in these states */ pdc_bus_stall_control_pipe(); return; } /* Find request target */ switch (bmRequestType&0x03) { case RECIP_DEVICE: /* DEVICE */ reply[0] = PDC_GETSTATUS_SELF_POWERED; reply[1]=0; break; case RECIP_INTERFACE: /* INTERFACE */ reply[0]=0; reply[1]=0; break; case RECIP_ENDPOINT: /* reply[0] needs to be 1 if the endpoint referred to in command[3] is stalled, otherwise 0 */ /* ep->pipe handle and context conversion */ handle = pdc_usb_to_epreg((command[4]&0x0F),(command[4]&0x80)); /* Check EP status */ ctrl_pipe_opr.handle = handle; ctrl_pipe_opr.context = (unsigned long) bus_dev; ctrl_pipe_opr.opr = PDC_GET_PIPE_STATUS; pdc_pipe_operation(&ctrl_pipe_opr); reply[0] = (ctrl_pipe_opr.pipe_status & PDC_PIPE_STALL) ? 1 : 0; reply[1]=0; break; default: /* UNDEFINED */ /* Stall endpoints 0 & 1 */ reply_len = 0; return; } /* Write this packet */ pdc_nofif_write_control_pipe(reply, reply_len); return;} /* End of pdc_bus_get_status() */void pdc_bus_usb_feature(__u8 *command){ __u8 bmRequestType = command[0]; __u8 inv_state = PDC_BUS_ADDRESSED; /* * For USB 2.0 Suppliment OTG 1.0 Specification, * Set feature will be accepted in default state also */ if(command[1]==SET_FEATURE) inv_state = PDC_BUS_DEFAULT; if((bus_dev->state < inv_state) || (command[0]&PDC_REQTYPE_DIR_MASK)) { /* You are not supposed to receive this in these states */ pdc_bus_stall_control_pipe(); return; } switch (bmRequestType & 0x03) { case RECIP_DEVICE: if (command[2]==PDC_FEATURE_REMOTE_WAKEUP) { pdc_nofif_write_control_pipe(NULL, 0); }#ifdef CONFIG_USB_HCDC_OTG else if ((command[2]==PDC_FEATURE_B_HNP_ENABLE)|| (command[2]==PDC_FEATURE_A_HNP_SUPPORT)|| (command[2]==PDC_FEATURE_A_ALTHNP_SUPPORT)) { pdc_nofif_write_control_pipe(NULL, 0); //inform the OTG module of this if( bus_dev->otg && bus_dev->otg->otg_notif) { bus_dev->otg->otg_notif(bus_dev->otg->priv_data, PDC_SET_HNP,command[2]); } }#endif /* CONFIG_USB_HCDC_OTG */ else { /* CF_WINDEX_FIX */ /* Stall endpoints 0 & 1 */ pdc_bus_stall_control_pipe(); } break; /* INTERFACE */ case RECIP_INTERFACE: pdc_nofif_write_control_pipe(NULL, 0); break; /* ENDPOINT */ case RECIP_ENDPOINT: { /* Find endpoint */ pdc_pipe_handle_t handle; int stall=(command[1]==SET_FEATURE); handle = pdc_usb_to_epreg((command[4]&0x0F),(command[4]&0x80)); detail_debug(("pdc: endpoint stall(%d)\n",handle)) /* Set/clear endpoint stall flag */ ctrl_pipe_opr.handle = handle; ctrl_pipe_opr.context = (unsigned long) bus_dev; if (stall) { ctrl_pipe_opr.opr = PDC_PIPE_STALL; } else if(handle > 0x01) { /* For Control In & Out already unstalled by HW */ ctrl_pipe_opr.opr = PDC_PIPE_UNSTALL; } pdc_pipe_operation(&ctrl_pipe_opr); /* 0-byte ACK */ pdc_nofif_write_control_pipe(NULL, 0); } break; /* UNDEFINED */ default: /* Stall endpoints 0 & 1 */ pdc_bus_stall_control_pipe(); break; }}/* Deal with get_descriptor */void pdc_bus_get_descriptor(__u8 *command){ __u8 *desc_ptr = NULL; __u16 desc_len = 0, req_len; func_debug(("get_descriptor(command=%p)\n",command)) if((bus_dev->state < PDC_BUS_ADDRESSED) && !(command[0]&PDC_REQTYPE_DIR_MASK)) { /* You are not supposed to receive this in these states */ pdc_bus_stall_control_pipe(); return; } switch( command[3]) { case PDC_DEV_DESC_TYPE: desc_ptr = device_desc; desc_len = sizeof(device_desc); break; case PDC_CONFIG_DESC_TYPE: if(command[2] < PDC_BUS_NUM_CONFIG) { desc_ptr = conf_desc; desc_len = sizeof(conf_desc); } break; case PDC_STRING_DESC_TYPE: switch(command[2]) { case 0: desc_ptr = unicode_string; desc_len = sizeof(unicode_string); break; case 1: desc_ptr = mfg_string; desc_len = sizeof(mfg_string); break; case 2: desc_ptr = product_string; desc_len = sizeof(product_string); break; case 3: desc_ptr = serial_string; desc_len = sizeof(serial_string); default: break; } break;#ifdef CONFIG_USB_HCDC_OTG case PDC_OTG_DESC_TYPE: desc_ptr = &conf_desc[PDC_CONFIG_DESC_LEN+PDC_INTF_DESC_LEN+2*PDC_EP_DESC_LEN]; desc_len = desc_ptr[0]; break;#endif /* CONFIG_USB_HCDC_OTG */ default: break; } if(desc_ptr) { /* Get max length that remote end wants */ req_len =command[6]|(command[7]<<8); if (desc_len > req_len ) { desc_len = req_len ; } pdc_nofif_write_control_pipe(desc_ptr, desc_len); } else { pdc_bus_stall_control_pipe(); } return;} /* End of pdc_bus_get_descriptor() */int pdc_nofif_write_control_pipe(__u8 *buff, __u16 len){ struct pdc_urb *urb = &bus_dev->ctrl_write_urb; if(!buff) len = 0; /* Fill the URB and submit it */ pdc_fill_non_iso_urb(urb, bus_dev->ctrl_pipe, PDC_PIPE_CONTROL, PDC_OPR_WRITE, buff, len, NULL,NULL); return pdc_submit_urb(urb);} /* End of pdc_nofif_write_control_pipe() */void pdc_bus_stall_control_pipe(void){ /* Stall Control Out Pipe */ ctrl_pipe_opr.handle = bus_dev->ctrl_pipe; ctrl_pipe_opr.context = (unsigned long) bus_dev; ctrl_pipe_opr.opr = PDC_PIPE_STALL; pdc_pipe_operation(&ctrl_pipe_opr);} /* End of pdc_bus_stall_control_pipe() */int pdc_bus_ctrl_pipe_notificaion(unsigned long notif_type, void *priv,unsigned char *cmd){ __u8 RequestType; __u8 bmRequest ; int result = -1; __u8 reply[2]; struct list_head *tmp; if(notif_type == PDC_SETUP_COMMAND) { /* SETUP Command from the control pipe */ RequestType = cmd[0] & 0x60; switch(RequestType) { case STANDARD_REQUEST: /* Process USB Standrad request */ bmRequest = cmd[1]; switch (bmRequest) { case GET_DESCRIPTOR: pdc_bus_get_descriptor(cmd); break; case CLEAR_FEATURE: case SET_FEATURE: pdc_bus_usb_feature(cmd); break; case SET_ADDRESS: /* * Set the address in the device controller * and send the status back to the Host */ if((bus_dev->state != PDC_BUS_DEFAULT) || (cmd[0]&PDC_REQTYPE_DIR_MASK)) { pdc_bus_stall_control_pipe(); } else { pdc_set_device_address((unsigned long)bus_dev->pdc_config,(cmd[2]&0x7F)); pdc_nofif_write_control_pipe(NULL, 0); bus_dev->state = PDC_BUS_ADDRESSED; } break; case SET_CONFIGURATION: pdc_bus_set_configuration(cmd); break; case SET_INTERFACE: pdc_bus_set_interface(cmd); break; case GET_CONFIGURATION: /* * Send the current configuration, the status stage is taken care * by the device controller */ if((bus_dev->state >= PDC_BUS_DEFAULT) && (cmd[0]&PDC_REQTYPE_DIR_MASK)) { reply[0] = bus_dev->configuration; pdc_nofif_write_control_pipe(reply, 1); } else { pdc_bus_stall_control_pipe(); } break; case GET_INTERFACE: /* * Send the current configuration, the status stage is taken care * by the device controller */ if((bus_dev->state >= PDC_BUS_CONFIGURED) && (cmd[0]&PDC_REQTYPE_DIR_MASK)) { reply[0] = bus_dev->interface; pdc_nofif_write_control_pipe(reply, 1); } else { /* You are not supposed to receive this in these states */ pdc_bus_stall_control_pipe(); } break; case GET_STATUS: pdc_bus_get_status(cmd); break; default: /* SET_DESCRIPTOR, SYNCH_FRAME TODO */ /* Other requests are not known to us */ pdc_bus_stall_control_pipe(); break; } break; case CLASS_REQUEST: case VENDOR_REQUEST: /* Process Class Vendor request */ /* Find the class driver that supports this request */ tmp = pdc_class_drv_list.next; while (tmp != &pdc_class_drv_list) { struct pdc_class_drv *cd = list_entry(tmp,struct pdc_class_drv, driver_list); tmp = tmp->next; if(cd->class_vendor) { /* Currently done for only one class driver */ result = cd->class_vendor(cd->priv_data, cmd); break; } } if(result == 0){ pdc_nofif_write_control_pipe(NULL, 0); } if(result < 0){ /* Stall control in and out pipes */ pdc_bus_stall_control_pipe(); } break; default: /* All other requests need to be stalled */ pdc_bus_stall_control_pipe(); break; } } return 0;} /* End of pdc_bus_ctrl_pipe_notifacaion() *//*-----------------------------------------------------------------* * External OTG interface functions * *-----------------------------------------------------------------*/#ifdef CONFIG_USB_HCDC_OTGint pdc_otg_register(pdc_otg_data_t *otg_data){ if( bus_dev && otg_data ) { detail_debug(("Registered OTG device with device\n")) otg_data->dc_priv_data = (void*)bus_dev; bus_dev->otg = otg_data; return 0; } return -1;}void pdc_otg_unregister(pdc_otg_data_t *otg_data) { if(bus_dev && otg_data) { detail_debug(("De-registered OTG device with device\n")) otg_data->dc_priv_data = NULL; bus_dev->otg = NULL; }}void pdc_otg_control(void *priv, unsigned long opr){ struct list_head *tmp; pdc_dev_control(opr); switch(opr) { case PDC_ENABLE: bus_dev->state = PDC_BUS_ATTACHED; break; case PDC_DISABLE: bus_dev->state = PDC_BUS_INIT; if(bus_dev->configuration) { bus_dev->configuration = 0; /* Find the class driver that supports this request */ tmp = pdc_class_drv_list.next; while (tmp != &pdc_class_drv_list) { struct pdc_class_drv *cd = list_entry(tmp,struct pdc_class_drv, driver_list); /* Currently done for only one class driver */ if(cd->set_config) cd->set_config(cd->priv_data,bus_dev->configuration); tmp = tmp->next; } } break; }}#endif /* CONFIG_USB_HCDC_OTG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -