📄 pdc_bus.c
字号:
}
/* 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_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_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_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_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;
__u8 address;
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 && bus_dev->state != PDC_BUS_ADDRESSED) || (cmd[0]&PDC_REQTYPE_DIR_MASK)) {
pdc_bus_stall_control_pipe();
} else {
address = (cmd[2]&0x7F);
pdc_set_device_address((unsigned long)bus_dev->pdc_config,address);
pdc_nofif_write_control_pipe(NULL, 0);
if(address) bus_dev->state = PDC_BUS_ADDRESSED;
else bus_dev->state = PDC_BUS_DEFAULT;
}
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_OTG
int pdc_otg_register(pdc_otg_data_t *otg_data)
{
if( bus_dev && otg_data ) {
otg_data->dc_priv_data = (void*)bus_dev;
bus_dev->otg = otg_data;
isp1362_printk(KERN_INFO __FILE__ ": Registered Driver usb-otg\n");
return 0;
}
return -1;
}
void pdc_otg_unregister(pdc_otg_data_t *otg_data)
{
if(bus_dev && otg_data) {
otg_data->dc_priv_data = NULL;
bus_dev->otg = NULL;
isp1362_printk(KERN_INFO __FILE__ ": De-registered Driver usb-otg\n");
}
}
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_OTG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -