📄 devmscd.c
字号:
} /* End of devmscd_set_command_res *//* * read URB complete function. * In case of IDLE state, this is a CBW. Other cases it is a data request * reurn */void devmscd_read_urb_complete(struct pdc_urb *urb){ struct devmscd_device *dev = &devmscd_dev; mscd_req_t *req; func_debug(("devmscd_read_urb_complete(%p)\n",urb)) switch(dev->state) { case DEVMSCD_IDLE: /* This is a CBW packet */ dev->tx_residue = (dev->cbw[8] | (dev->cbw[9] << 8)); dev->tx_residue |= ((dev->cbw[10] << 16) | (dev->cbw[11] << 24)); /* Copy the CBW tag to the CSW tag */ dev->csw[4] = dev->cbw[4]; dev->csw[5] = dev->cbw[5]; dev->csw[6] = dev->cbw[6]; dev->csw[7] = dev->cbw[7]; devmscd_change_state(dev, DEVMSCD_CBW); /* send this command to the mass storage bridge */ mscd_fill_req( (&bridge_req), MSCD_COMMAND, (&dev->cbw[DEVMSCD_CBW_WRAPPER]), (DEVMSCD_CBW_LENGTH - DEVMSCD_CBW_WRAPPER), devmscd_set_command_res, NULL); mscdbridge_submit_req(&bridge_req); if(dev->cbw[12] & DEVMSCD_CBWFLAG_IN) { /* Data to Host, so Data out from Device */ devmscd_change_state(dev, DEVMSCD_DATA_OUT); } else { /* Data from Host, so Data in to Device */ devmscd_change_state(dev, DEVMSCD_DATA_IN); } break; case DEVMSCD_DATA_IN: dev->tx_residue -= urb->actual_length; req = bridge_read_req; if(req) { /* Call the call back function */ req->res_data_len = urb->actual_length; req->status = MSCD_SUCCESS; bridge_read_req = NULL; if(req->complete) req->complete(req); } break; } urb->status = PDC_URB_COMPLETE;} /* End of devmscd_read_urb_complete *//* * Call the call back function of the bridge request * If the status stage is already sent by the bridge, finish the status * stage */void devmscd_write_urb_complete(struct pdc_urb *urb){ struct devmscd_device *dev = &devmscd_dev; mscd_req_t *req; struct pdc_pipe_opr bulk_pipe_opr; func_debug(("devmscd_write_urb_complete(%p)\n",urb)) dev->tx_residue -= urb->actual_length; if(dev->status_queue) { if(dev->tx_residue) { /* Send a stall */ bulk_pipe_opr.handle = dev->data_out_pipe; bulk_pipe_opr.context = (unsigned long) dev; bulk_pipe_opr.opr = PDC_PIPE_STALL; mdelay(3); pdc_pipe_operation(&bulk_pipe_opr); dev->csw[8] = dev->tx_residue & 0xFF; dev->csw[9] = (dev->tx_residue >> 8) & 0xFF; dev->csw[10] = (dev->tx_residue >> 16) & 0xFF; dev->csw[11] = (dev->tx_residue >> 24) & 0xFF; } /* Already status is received, so send the status */ devmscd_read_data(dev->cbw,DEVMSCD_CBW_LENGTH); devmscd_write_data(dev->csw, DEVMSCD_CSW_LENGTH); devmscd_change_state(dev, DEVMSCD_IDLE); dev->status_queue = 0; } if(devmscd_dev.state != DEVMSCD_CSW) { /* Update the transfer residue */// devmscd_dev.tx_residue -= urb->actual_length; req = bridge_write_req; if(req) { /* call the bridge call back function */ req->res_data_len = urb->actual_length; req->status = MSCD_SUCCESS; bridge_write_req = NULL; if(req->complete) req->complete(req); } } urb->status = PDC_URB_COMPLETE;} /* End of devmscd_write_urb_complete *//* * Bulk Only Trnasport, Mass storage reset. * Go back to Idle state, no transfer residue. */void devmscd_reset(struct devmscd_device *dev){ func_debug(("devmscd_reset(%p)\n",dev)) devmscd_change_state(dev, DEVMSCD_IDLE); dev->tx_residue = 0x00; dev->status_queue = 0; read_urb.status = PDC_URB_COMPLETE; write_urb.status = PDC_URB_COMPLETE; /* Initialize the CSW signature */ dev->csw[0] = 0x55; dev->csw[1] = 0x53; dev->csw[2] = 0x42; dev->csw[3] = 0x53;} /* End of devmscd_reset */int devmscd_configure(void *__dev, unsigned char cfg){ struct devmscd_device *dev = (struct devmscd_device *)__dev; if(dev) { if(cfg) { devmscd_reset(dev); dev->data_in_pipe = PDC_INV_PIPE_HANDLE; dev->data_out_pipe = PDC_INV_PIPE_HANDLE; /* Configure the device */ dev->data_in_pipe = pdc_open_pipe(&bulk_pipe_desc[0]); if(dev->data_in_pipe != PDC_INV_PIPE_HANDLE) { dev->data_out_pipe = pdc_open_pipe(&bulk_pipe_desc[1]); if(dev->data_out_pipe != PDC_INV_PIPE_HANDLE) { /* Start waiting for CBW data */ devmscd_read_data(dev->cbw,DEVMSCD_CBW_LENGTH); } else { pdc_close_pipe(dev->data_in_pipe); dev->data_in_pipe = PDC_INV_PIPE_HANDLE; } } } else { /* Cancel all data requests to the device */ if(read_urb.status == PDC_URB_PENDING) pdc_cancel_urb(&read_urb); /* Un configure the device */ if(dev->data_in_pipe != PDC_INV_PIPE_HANDLE) { pdc_close_pipe(dev->data_in_pipe); dev->data_in_pipe = PDC_INV_PIPE_HANDLE; } if(dev->data_out_pipe != PDC_INV_PIPE_HANDLE) { pdc_close_pipe(dev->data_out_pipe); dev->data_out_pipe = PDC_INV_PIPE_HANDLE; } devmscd_reset(dev); } } return 0;}/* * The class request can have the following return values * == 0 success and no data to send/receive * > 0 success data stage is needed through dev urb * < 0 failure of the command, send stall * */int devmscd_class_req(void *__dev, __u8 *req){ __u8 cls_req = req[1]; int result; struct devmscd_device *dev = (struct devmscd_device *)__dev; func_debug(("devmscd_class_req(%p)\n",req)) switch(cls_req) { case DEVMSCD_MS_RESET: detail_debug(("DEVMSCD_RESET\n")) /* Inform the mass storage bridge about the reset */ mscd_fill_req(&bridge_req, MSCDBRIDGE_RESET, NULL, 0x00, NULL, NULL); mscdbridge_submit_req(&bridge_req); /* Reset internal variables */ devmscd_reset(dev); result = 0; break; case DEVMSCD_GET_MAX_LUN: /* * This command is not supported by this class driver */ result = -1; break; default: result = -1; break; } return result;} /* devmscd_class_req */struct pdc_class_drv devmscd_drv = { name: DRIVER_NAME, class_vendor: devmscd_class_req, set_config: devmscd_configure, set_intf: NULL, priv_data: &devmscd_dev,};/* * module initialization function * Initialize the physical disk. * Register the class driver with the functional interface to the * peripheral controller driver and wait for the it to call connect * function */static int __init devmscd_module_init (void) { int result; func_debug(("devmscd_module_init(void)\n")) bridge_read_req = NULL; bridge_write_req = NULL; bulk_pipe_desc[0].ep = 1; bulk_pipe_desc[0].ep_dir = PDC_EP_DIR_OUT; bulk_pipe_desc[0].context = (unsigned long)(&devmscd_drv); bulk_pipe_desc[0].priv = (void*)(&devmscd_drv); bulk_pipe_desc[0].notify = NULL; bulk_pipe_desc[1].ep = 2; bulk_pipe_desc[1].ep_dir = PDC_EP_DIR_IN; bulk_pipe_desc[1].context = (unsigned long)(&devmscd_drv); bulk_pipe_desc[1].priv = (void*)(&devmscd_drv); bulk_pipe_desc[1].notify = NULL; /* Initialize mass storage bridge */ mscd_fill_req(&bridge_req, MSCDBRIDGE_INIT, NULL, 0x00, NULL, NULL); result = mscdbridge_submit_req(&bridge_req); if(result < 0) return result; /* register to the device controller driver */ return pdc_register_class_drv(&devmscd_drv);} /* End of devmscd_module_init *//* * module close function * shutdown the physical disk * unregister the class driver from the peripheral controller driver. */static void __exit devmscd_module_cleanup (void) { func_debug(("devmscd_module_cleanup(void)\n")) /* de-register to the device controller driver */ pdc_deregister_class_drv(&devmscd_drv); /* Notify the bridge that we are going off */ mscd_fill_req(&bridge_req, MSCDBRIDGE_DEINIT, NULL, 0x00, NULL, NULL); mscdbridge_submit_req(&bridge_req); return;} /* End of devmscd_module_cleanup */module_init (devmscd_module_init);module_exit (devmscd_module_cleanup);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_AUTHOR(DRIVER_AUTHOR);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -