static int init_freecom(struct us_data *us) { int result; char *buffer = us->iobuf; result = usb_stor_control_msg(us, us->recv_ctrl_pipe, 0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ); buffer[32] = '\0'; US_DEBUGP("String returned from FC init is: %s\n", buffer); result = usb_stor_control_msg(us, us->send_ctrl_pipe, 0x4d, 0x40, 0x24d8, 0x0, NULL, 0x0, 3*HZ); US_DEBUGP("result from activate reset is %d\n", result); mdelay(250); result = usb_stor_control_msg(us, us->send_ctrl_pipe, 0x4d, 0x40, 0x24f8, 0x0, NULL, 0x0, 3*HZ); US_DEBUGP("result from clear reset is %d\n", result); mdelay(3 * 1000); return USB_STOR_TRANSPORT_GOOD; }
/* Determine what the maximum LUN supported is */ int usb_stor_Bulk_max_lun(struct us_data *us) { int result; /* issue the command */ us->iobuf[0] = 0; result = usb_stor_control_msg(us, us->recv_ctrl_pipe, US_BULK_GET_MAX_LUN, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, us->iobuf, 1, 10*HZ); US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", result, us->iobuf[0]); /* if we have a successful request, return the result */ if (result > 0) return us->iobuf[0]; /* * Some devices don't like GetMaxLUN. They may STALL the control * pipe, they may return a zero-length result, they may do nothing at * all and timeout, or they may fail in even more bizarrely creative * ways. In these cases the best approach is to use the default * value: only one LUN. */ return 0; }
int usb_modem_init(struct us_data *us) { printk("====modem_init===>\n"); usb_stor_control_msg(us, us->send_ctrl_pipe, USB_REQ_CLEAR_FEATURE, USB_TYPE_STANDARD | USB_RECIP_ENDPOINT,0x0, 0x85, NULL, 0x0, 1000); return -ENODEV; }
/* This is the common part of the device reset code. * * It's handy that every transport mechanism uses the control endpoint for * resets. * * Basically, we send a reset with a 20-second timeout, so we don't get * jammed attempting to do the reset. */ static int usb_stor_reset_common(struct us_data *us, u8 request, u8 requesttype, u16 value, u16 index, void *data, u16 size) { int result; int result2; int rc = FAILED; /* Let the SCSI layer know we are doing a reset, set the * RESETTING bit, and clear the ABORTING bit so that the reset * may proceed. */ scsi_lock(us_to_host(us)); usb_stor_report_device_reset(us); set_bit(US_FLIDX_RESETTING, &us->flags); clear_bit(US_FLIDX_ABORTING, &us->flags); scsi_unlock(us_to_host(us)); /* A 20-second timeout may seem rather long, but a LaCie * StudioDrive USB2 device takes 16+ seconds to get going * following a powerup or USB attach event. */ result = usb_stor_control_msg(us, us->send_ctrl_pipe, request, requesttype, value, index, data, size, 20*HZ); if (result < 0) { US_DEBUGP("Soft reset failed: %d\n", result); goto Done; } /* Give the device some time to recover from the reset, * but don't delay disconnect processing. */ wait_event_interruptible_timeout(us->delay_wait, test_bit(US_FLIDX_DISCONNECTING, &us->flags), HZ*6); if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { US_DEBUGP("Reset interrupted by disconnect\n"); goto Done; } US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n"); result = usb_stor_clear_halt(us, us->recv_bulk_pipe); US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n"); result2 = usb_stor_clear_halt(us, us->send_bulk_pipe); /* return a result code based on the result of the control message */ if (result < 0 || result2 < 0) { US_DEBUGP("Soft reset failed\n"); goto Done; } US_DEBUGP("Soft reset done\n"); rc = SUCCESS; Done: clear_bit(US_FLIDX_RESETTING, &us->flags); return rc; }
/* * Control/Bulk transport */ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us) { int result; /* COMMAND STAGE */ /* let's send the command via the control pipe */ result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0), US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, srb->cmnd, srb->cmd_len); /* check the return code for the command */ US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result); if (result < 0) { /* if the command was aborted, indicate that */ if (result == -ECONNRESET) return USB_STOR_TRANSPORT_ABORTED; /* a stall is a fatal condition from the device */ if (result == -EPIPE) { US_DEBUGP("-- Stall on control pipe. Clearing\n"); result = usb_stor_clear_halt(us, usb_sndctrlpipe(us->pusb_dev, 0)); /* if the command was aborted, indicate that */ if (result == -ECONNRESET) return USB_STOR_TRANSPORT_ABORTED; return USB_STOR_TRANSPORT_FAILED; } /* Uh oh... serious problem here */ return USB_STOR_TRANSPORT_ERROR; } /* DATA STAGE */ /* transfer the data payload for this command, if one exists*/ if (usb_stor_transfer_length(srb)) { usb_stor_transfer(srb, us); result = srb->result; US_DEBUGP("CB data stage result is 0x%x\n", result); /* report any errors */ if (result == US_BULK_TRANSFER_ABORTED) { return USB_STOR_TRANSPORT_ABORTED; } if (result == US_BULK_TRANSFER_FAILED) { return USB_STOR_TRANSPORT_FAILED; } } /* STATUS STAGE */ /* NOTE: CB does not have a status stage. Silly, I know. So * we have to catch this at a higher level. */ return USB_STOR_TRANSPORT_GOOD; }
int usb_stor_zte_init(struct us_data *us) { int result; result =usb_stor_control_msg(us,us->send_ctrl_pipe, 0xA1, 0xC0, 0x01,0x0,NULL,0x0,1000); printk("usb_stor_zte_int result is %d\n",result); return 0; }
/* This places the S10 E220 devices in multi-port mode */ int usb_stor_S10_e220_init(struct us_data *us) { int result; result = usb_stor_control_msg(us, us->send_ctrl_pipe, USB_REQ_SET_FEATURE, USB_TYPE_STANDARD | USB_RECIP_DEVICE, 0x01, 0x0, NULL, 0x0, 1000); US_DEBUGP("Huawei mode set result is %d\n", result); return 0; }
/* * This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target * mode */ int usb_stor_euscsi_init(struct us_data *us) { int result; usb_stor_dbg(us, "Attempting to init eUSCSI bridge...\n"); result = usb_stor_control_msg(us, us->send_ctrl_pipe, 0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR, 0x01, 0x0, NULL, 0x0, 5 * HZ); usb_stor_dbg(us, "-- result is %d\n", result); return 0; }
/* This places the HUAWEI E220 devices in multi-port mode */ int usb_stor_huawei_e220_init(struct us_data *us) { int result; us->iobuf[0] = 0x1; result = usb_stor_control_msg(us, us->send_ctrl_pipe, USB_REQ_SET_FEATURE, USB_TYPE_STANDARD | USB_RECIP_DEVICE, 0x01, 0x0, us->iobuf, 0x1, 1000); US_DEBUGP("usb_control_msg performing result is %d\n", result); return (result ? 0 : -1); }
static int init_freecom(struct us_data *us) { int result; char *buffer = us->iobuf; /* * The DMA-mapped I/O buffer is 64 bytes long, just right for * all our packets. No need to allocate any extra buffer space. */ result = usb_stor_control_msg(us, us->recv_ctrl_pipe, 0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ); buffer[32] = '\0'; usb_stor_dbg(us, "String returned from FC init is: %s\n", buffer); /* * Special thanks to the people at Freecom for providing me with * this "magic sequence", which they use in their Windows and MacOS * drivers to make sure that all the attached perhiperals are * properly reset. */ /* send reset */ result = usb_stor_control_msg(us, us->send_ctrl_pipe, 0x4d, 0x40, 0x24d8, 0x0, NULL, 0x0, 3*HZ); usb_stor_dbg(us, "result from activate reset is %d\n", result); /* wait 250ms */ mdelay(250); /* clear reset */ result = usb_stor_control_msg(us, us->send_ctrl_pipe, 0x4d, 0x40, 0x24f8, 0x0, NULL, 0x0, 3*HZ); usb_stor_dbg(us, "result from clear reset is %d\n", result); /* wait 3 seconds */ mdelay(3 * 1000); return USB_STOR_TRANSPORT_GOOD; }
//AC560--ZTE-- 0x19d20026->0x19d20094 before convert to modem,don't report disk dev int usb_stor_ZTE_AC580_init(struct us_data *us) // PID = 0x0026 { #if 0 int result = 0; int act_len = 0; result = usb_stor_control_msg(us, us->send_ctrl_pipe,USB_REQ_CLEAR_FEATURE, USB_TYPE_STANDARD | USB_RECIP_ENDPOINT,0x0, 0x89, NULL, 0x0, 1000); US_DEBUGP("usb_stor_control_msg performing result is %d\n", result); printk("====AC580/AC560===>usb_stor_control_msg performing result is %d\n", result); result = usb_stor_control_msg(us, us->send_ctrl_pipe,USB_REQ_CLEAR_FEATURE, USB_TYPE_STANDARD | USB_RECIP_ENDPOINT,0x0, 0x9, NULL, 0x0, 1000); US_DEBUGP("usb_stor_control_msg performing result is %d\n", result); printk("====AC580/AC560===>usb_stor_control_msg performing result is %d\n", result); return (result ? 0 : -ENODEV); #else return -ENODEV; #endif }
/* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target * mode */ int usb_stor_euscsi_init(struct us_data *us) { int result; US_DEBUGP("Attempting to init eUSCSI bridge...\n"); us->iobuf[0] = 0x1; result = usb_stor_control_msg(us, us->send_ctrl_pipe, 0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR, 0x01, 0x0, us->iobuf, 0x1, 5000); US_DEBUGP("-- result is %d\n", result); return 0; }
/* * Control/Bulk transport */ int UMAS_CbTransport(SCSI_CMD_T *srb, UMAS_DATA_T *umas) { int result; /* COMMAND STAGE */ /* let's send the command via the control pipe */ result = usb_stor_control_msg(umas, usb_sndctrlpipe(umas->pusb_dev, 0), US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, umas->ifnum, srb->cmnd, srb->cmd_len); /* check the return code for the command */ UMAS_VDEBUG("UMAS_CbTransport - Call to usb_stor_control_msg() returned %d\n", result); if(result < 0) { /* if the command was aborted, indicate that */ if(result == USB_ERR_NOENT) return USB_STOR_TRANSPORT_ABORTED; /* a stall is a fatal condition from the device */ if(result == USB_ERR_PIPE) { UMAS_DEBUG("UMAS_CbTransport - Stall on control pipe. Clearing\n"); result = clear_halt(umas->pusb_dev, usb_sndctrlpipe(umas->pusb_dev, 0)); UMAS_DEBUG("UMAS_CbTransport - clear_halt() returns %d\n", result); return USB_STOR_TRANSPORT_FAILED; } /* Uh oh... serious problem here */ return USB_STOR_TRANSPORT_ERROR; } /* DATA STAGE */ /* transfer the data payload for this command, if one exists */ if(usb_stor_transfer_length(srb)) { us_transfer(srb, umas); UMAS_VDEBUG("UMAS_CbTransport - CB data stage result is 0x%x\n", srb->result); /* if it was aborted, we need to indicate that */ if(srb->result == USB_STOR_TRANSPORT_ABORTED) return USB_STOR_TRANSPORT_ABORTED; } /* STATUS STAGE */ /* NOTE: CB does not have a status stage. Silly, I know. So * we have to catch this at a higher level. */ return USB_STOR_TRANSPORT_GOOD; }
/* This places the HUAWEI E220 devices in multi-port mode */ int usb_stor_huawei_e220_init(struct us_data *us) { #if 0 int result; result = usb_stor_control_msg(us, us->send_ctrl_pipe, USB_REQ_SET_FEATURE, USB_TYPE_STANDARD | USB_RECIP_DEVICE, 0x01, 0x0, NULL, 0x0, 1000); US_DEBUGP("Huawei mode set result is %d\n", result); return 0; #else printk("====usb_stor_huawei_e220_init===>\n"); return -ENODEV; #endif }
/* * This is the common part of the device reset code. * * It's handy that every transport mechanism uses the control endpoint for * resets. * * Basically, we send a reset with a 5-second timeout, so we don't get * jammed attempting to do the reset. */ static int usb_stor_reset_common(struct us_data *us, u8 request, u8 requesttype, u16 value, u16 index, void *data, u16 size) { int result; int result2; if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) { usb_stor_dbg(us, "No reset during disconnect\n"); return -EIO; } result = usb_stor_control_msg(us, us->send_ctrl_pipe, request, requesttype, value, index, data, size, 5*HZ); if (result < 0) { usb_stor_dbg(us, "Soft reset failed: %d\n", result); return result; } /* * Give the device some time to recover from the reset, * but don't delay disconnect processing. */ wait_event_interruptible_timeout(us->delay_wait, test_bit(US_FLIDX_DISCONNECTING, &us->dflags), HZ*6); if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) { usb_stor_dbg(us, "Reset interrupted by disconnect\n"); return -EIO; } usb_stor_dbg(us, "Soft reset: clearing bulk-in endpoint halt\n"); result = usb_stor_clear_halt(us, us->recv_bulk_pipe); usb_stor_dbg(us, "Soft reset: clearing bulk-out endpoint halt\n"); result2 = usb_stor_clear_halt(us, us->send_bulk_pipe); /* return a result code based on the result of the clear-halts */ if (result >= 0) result = result2; if (result < 0) usb_stor_dbg(us, "Soft reset failed\n"); else usb_stor_dbg(us, "Soft reset done\n"); return result; }
/* * usb_stor_reset_common() */ static int usb_stor_reset_common(struct us_data *us, u8 request, u8 requesttype, u16 value, u16 index, void *data, u16 size) { int result; int result2; /* pr_info("transport --- usb_stor_reset_common\n"); */ if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) { /* pr_info("No reset during disconnect\n"); */ return -EIO; } result = usb_stor_control_msg(us, us->send_ctrl_pipe, request, requesttype, value, index, data, size, 5*HZ); if (result < 0) { /* pr_info("Soft reset failed: %d\n", result); */ return result; } wait_event_interruptible_timeout(us->delay_wait, test_bit(US_FLIDX_DISCONNECTING, &us->dflags), HZ*6); if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) { /* pr_info("Reset interrupted by disconnect\n"); */ return -EIO; } /* pr_info("Soft reset: clearing bulk-in endpoint halt\n"); */ result = usb_stor_clear_halt(us, us->recv_bulk_pipe); /* pr_info("Soft reset: clearing bulk-out endpoint halt\n"); */ result2 = usb_stor_clear_halt(us, us->send_bulk_pipe); /* return a result code based on the result of the clear-halts */ if (result >= 0) result = result2; /* if (result < 0) */ /* pr_info("Soft reset failed\n"); */ /* else */ /* pr_info("Soft reset done\n"); */ return result; }
int usb_stor_clear_halt(struct us_data *us, unsigned int pipe) { int result; int endp = usb_pipeendpoint(pipe); if (usb_pipein (pipe)) endp |= USB_DIR_IN; result = usb_stor_control_msg(us, us->send_ctrl_pipe, USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, USB_ENDPOINT_HALT, endp, NULL, 0, 3*HZ); if (result >= 0) usb_reset_endpoint(us->pusb_dev, endp); US_DEBUGP("%s: result = %d\n", __func__, result); return result; }
static int usb_stor_reset_common(struct us_data *us, u8 request, u8 requesttype, u16 value, u16 index, void *data, u16 size) { int result; int result2; if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) { US_DEBUGP("No reset during disconnect\n"); return -EIO; } result = usb_stor_control_msg(us, us->send_ctrl_pipe, request, requesttype, value, index, data, size, 5*HZ); if (result < 0) { US_DEBUGP("Soft reset failed: %d\n", result); return result; } wait_event_interruptible_timeout(us->delay_wait, test_bit(US_FLIDX_DISCONNECTING, &us->dflags), HZ*6); if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) { US_DEBUGP("Reset interrupted by disconnect\n"); return -EIO; } US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n"); result = usb_stor_clear_halt(us, us->recv_bulk_pipe); US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n"); result2 = usb_stor_clear_halt(us, us->send_bulk_pipe); if (result >= 0) result = result2; if (result < 0) US_DEBUGP("Soft reset failed\n"); else US_DEBUGP("Soft reset done\n"); return result; }
/* This is a version of usb_clear_halt() that allows early termination and * doesn't read the status from the device -- this is because some devices * crash their internal firmware when the status is requested after a halt. * * A definitive list of these 'bad' devices is too difficult to maintain or * make complete enough to be useful. This problem was first observed on the * Hagiwara FlashGate DUAL unit. However, bus traces reveal that neither * MacOS nor Windows checks the status after clearing a halt. * * Since many vendors in this space limit their testing to interoperability * with these two OSes, specification violations like this one are common. */ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe) { int result; int endp = usb_pipeendpoint(pipe); if (usb_pipein (pipe)) endp |= USB_DIR_IN; result = usb_stor_control_msg(us, us->send_ctrl_pipe, USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, USB_ENDPOINT_HALT, endp, NULL, 0, 3*HZ); /* reset the endpoint toggle */ usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); US_DEBUGP("%s: result = %d\n", __FUNCTION__, result); return result; }
/* Determine what the maximum LUN supported is */ static int rts51x_get_max_lun(struct us_data *us) { int result; /* issue the command */ us->iobuf[0] = 0; result = usb_stor_control_msg(us, us->recv_ctrl_pipe, US_BULK_GET_MAX_LUN, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, us->iobuf, 1, 10*HZ); US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", result, us->iobuf[0]); /* if we have a successful request, return the result */ if (result > 0) return us->iobuf[0]; return 0; }
//----- usb_stor_clear_halt() --------------------- int usb_stor_clear_halt(struct us_data *us, unsigned int pipe) { int result; int endp = usb_pipeendpoint(pipe); //printk("transport --- usb_stor_clear_halt\n"); if (usb_pipein (pipe)) endp |= USB_DIR_IN; result = usb_stor_control_msg(us, us->send_ctrl_pipe, USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, USB_ENDPOINT_HALT, endp, NULL, 0, 3*HZ); /* reset the endpoint toggle */ if (result >= 0) //usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); usb_reset_endpoint(us->pusb_dev, endp); return result; }
int usb_stor_Bulk_max_lun(struct us_data *us) { int result; us->iobuf[0] = 0; result = usb_stor_control_msg(us, us->recv_ctrl_pipe, US_BULK_GET_MAX_LUN, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, us->iobuf, 1, 10*HZ); US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", result, us->iobuf[0]); if (result > 0) return us->iobuf[0]; return 0; }
/* Determine what the maximum LUN supported is */ int usb_stor_Bulk_max_lun(struct us_data *us) { int result; /* issue the command */ us->iobuf[0] = 0; result = usb_stor_control_msg(us, us->recv_ctrl_pipe, US_BULK_GET_MAX_LUN, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, us->iobuf, 1, HZ); US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", result, us->iobuf[0]); /* if we have a successful request, return the result */ if (result > 0) return us->iobuf[0]; /* * Some devices (i.e. Iomega Zip100) need this -- apparently * the bulk pipes get STALLed when the GetMaxLUN request is * processed. This is, in theory, harmless to all other devices * (regardless of if they stall or not). */ if (result == -EPIPE) { usb_stor_clear_halt(us, us->recv_bulk_pipe); usb_stor_clear_halt(us, us->send_bulk_pipe); } /* * Some devices don't like GetMaxLUN. They may STALL the control * pipe, they may return a zero-length result, they may do nothing at * all and timeout, or they may fail in even more bizarrely creative * ways. In these cases the best approach is to use the default * value: only one LUN. */ return 0; }
/* Determine what the maximum LUN supported is */ int usb_stor_Bulk_max_lun(struct us_data *us) { int result; /* issue the command */ us->iobuf[0] = 0; result = usb_stor_control_msg(us, us->recv_ctrl_pipe, US_BULK_GET_MAX_LUN, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, us->iobuf, 1, 10*HZ); usb_stor_dbg(us, "GetMaxLUN command result is %d, data is %d\n", result, us->iobuf[0]); /* * If we have a successful request, return the result if valid. The * CBW LUN field is 4 bits wide, so the value reported by the device * should fit into that. */ if (result > 0) { if (us->iobuf[0] < 16) { return us->iobuf[0]; } else { dev_info(&us->pusb_intf->dev, "Max LUN %d is not valid, using 0 instead", us->iobuf[0]); } } /* * Some devices don't like GetMaxLUN. They may STALL the control * pipe, they may return a zero-length result, they may do nothing at * all and timeout, or they may fail in even more bizarrely creative * ways. In these cases the best approach is to use the default * value: only one LUN. */ return 0; }
/* * usb_stor_Bulk_max_lun() */ int usb_stor_Bulk_max_lun(struct us_data *us) { int result; /* pr_info("transport --- usb_stor_Bulk_max_lun\n"); */ /* issue the command */ us->iobuf[0] = 0; result = usb_stor_control_msg(us, us->recv_ctrl_pipe, US_BULK_GET_MAX_LUN, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, us->iobuf, 1, HZ); /* pr_info("GetMaxLUN command result is %d, data is %d\n", result, us->iobuf[0]); */ /* if we have a successful request, return the result */ if (result > 0) return us->iobuf[0]; return 0; }
/* This is a version of usb_clear_halt() that doesn't read the status from * the device -- this is because some devices crash their internal firmware * when the status is requested after a halt */ int usb_stor_clear_halt(struct us_data *us, int pipe) { int result; int endp = usb_pipeendpoint(pipe) | (usb_pipein(pipe) << 7); result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev, 0), USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0); /* note: no 3*HZ timeout */ US_DEBUGP("usb_stor_clear_halt: result=%d\n", result); /* this is a failure case */ if (result < 0) return result; /* reset the toggles and endpoint flags */ usb_endpoint_running(us->pusb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); return 0; }
int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us) { int result; /* Set up for status notification */ atomic_set(us->ip_wanted, 1); /* re-initialize the mutex so that we avoid any races with * early/late IRQs from previous commands */ init_MUTEX_LOCKED(&(us->ip_waitq)); /* COMMAND STAGE */ /* let's send the command via the control pipe */ result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0), US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, srb->cmnd, srb->cmd_len); /* check the return code for the command */ US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result); if (result < 0) { /* Reset flag for status notification */ atomic_set(us->ip_wanted, 0); } /* if the command was aborted, indicate that */ if (result == -ECONNRESET) return USB_STOR_TRANSPORT_ABORTED; /* STALL must be cleared when it is detected */ if (result == -EPIPE) { US_DEBUGP("-- Stall on control pipe. Clearing\n"); result = usb_stor_clear_halt(us, usb_sndctrlpipe(us->pusb_dev, 0)); /* if the command was aborted, indicate that */ if (result == -ECONNRESET) return USB_STOR_TRANSPORT_ABORTED; return USB_STOR_TRANSPORT_FAILED; } if (result < 0) { /* Uh oh... serious problem here */ return USB_STOR_TRANSPORT_ERROR; } /* DATA STAGE */ /* transfer the data payload for this command, if one exists*/ if (usb_stor_transfer_length(srb)) { usb_stor_transfer(srb, us); result = srb->result; US_DEBUGP("CBI data stage result is 0x%x\n", result); /* report any errors */ if (result == US_BULK_TRANSFER_ABORTED) { atomic_set(us->ip_wanted, 0); return USB_STOR_TRANSPORT_ABORTED; } if (result == US_BULK_TRANSFER_FAILED) { atomic_set(us->ip_wanted, 0); return USB_STOR_TRANSPORT_FAILED; } } /* STATUS STAGE */ /* go to sleep until we get this interrupt */ US_DEBUGP("Current value of ip_waitq is: %d\n", atomic_read(&us->ip_waitq.count)); down(&(us->ip_waitq)); /* if we were woken up by an abort instead of the actual interrupt */ if (atomic_read(us->ip_wanted)) { US_DEBUGP("Did not get interrupt on CBI\n"); atomic_set(us->ip_wanted, 0); return USB_STOR_TRANSPORT_ABORTED; } US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", us->irqdata[0], us->irqdata[1]); /* UFI gives us ASC and ASCQ, like a request sense * * REQUEST_SENSE and INQUIRY don't affect the sense data on UFI * devices, so we ignore the information for those commands. Note * that this means we could be ignoring a real error on these * commands, but that can't be helped. */ if (us->subclass == US_SC_UFI) { if (srb->cmnd[0] == REQUEST_SENSE || srb->cmnd[0] == INQUIRY) return USB_STOR_TRANSPORT_GOOD; else if (((unsigned char*)us->irq_urb->transfer_buffer)[0]) return USB_STOR_TRANSPORT_FAILED; else return USB_STOR_TRANSPORT_GOOD; } /* If not UFI, we interpret the data as a result code * The first byte should always be a 0x0 * The second byte & 0x0F should be 0x0 for good, otherwise error */ if (us->irqdata[0]) { US_DEBUGP("CBI IRQ data showed reserved bType %d\n", us->irqdata[0]); return USB_STOR_TRANSPORT_ERROR; } switch (us->irqdata[1] & 0x0F) { case 0x00: return USB_STOR_TRANSPORT_GOOD; case 0x01: return USB_STOR_TRANSPORT_FAILED; default: return USB_STOR_TRANSPORT_ERROR; } /* we should never get here, but if we do, we're in trouble */ return USB_STOR_TRANSPORT_ERROR; }
int UMAS_CbiTransport(SCSI_CMD_T *srb, UMAS_DATA_T *umas) { int result; /* Set up for status notification */ umas->ip_wanted = 1; /* re-initialize the mutex so that we avoid any races with * early/late IRQs from previous commands */ /* COMMAND STAGE */ /* let's send the command via the control pipe */ result = usb_stor_control_msg(umas, usb_sndctrlpipe(umas->pusb_dev, 0), US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, umas->ifnum, srb->cmnd, srb->cmd_len); /* check the return code for the command */ UMAS_VDEBUG("Call to usb_stor_control_msg() returned %d\n", result); if(result < 0) { /* if the command was aborted, indicate that */ if(result == USB_ERR_NOENT) return USB_STOR_TRANSPORT_ABORTED; /* STALL must be cleared when they are detected */ if(result == USB_ERR_PIPE) { UMAS_VDEBUG("-- Stall on control pipe. Clearing\n"); result = clear_halt(umas->pusb_dev, usb_sndctrlpipe(umas->pusb_dev, 0)); UMAS_VDEBUG("-- clear_halt() returns %d\n", result); return USB_STOR_TRANSPORT_FAILED; } /* Uh oh... serious problem here */ return USB_STOR_TRANSPORT_ERROR; } /* DATA STAGE */ /* transfer the data payload for this command, if one exists*/ if(usb_stor_transfer_length(srb)) { us_transfer(srb, umas); UMAS_VDEBUG("CBI data stage result is 0x%x\n", srb->result); /* if it was aborted, we need to indicate that */ if(srb->result == USB_STOR_TRANSPORT_ABORTED) return USB_STOR_TRANSPORT_ABORTED; } /* STATUS STAGE */ //UMAS_VDEBUG("Current value of ip_waitq is: %d\n", umas->ip_waitq.count); /* if we were woken up by an abort instead of the actual interrupt */ if(umas->ip_wanted) { UMAS_DEBUG("Did not get interrupt on CBI\n"); umas->ip_wanted = 0; return USB_STOR_TRANSPORT_ABORTED; } UMAS_VDEBUG("Got interrupt data (0x%x, 0x%x)\n", umas->irqdata[0], umas->irqdata[1]); /* * UFI gives umas ASC and ASCQ, like a request sense * * REQUEST_SENSE and INQUIRY don't affect the sense data on UFI * devices, so we ignore the information for those commands. Note * that this means we could be ignoring a real error on these * commands, but that can't be helped. */ if(umas->subclass == UMAS_SC_UFI) { if((srb->cmnd[0] == REQUEST_SENSE) || (srb->cmnd[0] == INQUIRY)) return USB_STOR_TRANSPORT_GOOD; else { if(((uint8_t*)umas->irq_urb->transfer_buffer)[0]) return USB_STOR_TRANSPORT_FAILED; else return USB_STOR_TRANSPORT_GOOD; } } /* * If not UFI, we interpret the data as a result code * The first byte should always be a 0x0 * The second byte & 0x0F should be 0x0 for good, otherwise error */ if(umas->irqdata[0]) { UMAS_VDEBUG("CBI IRQ data showed reserved bType %d\n", umas->irqdata[0]); return USB_STOR_TRANSPORT_ERROR; } switch(umas->irqdata[1] & 0x0F) { case 0x00: return USB_STOR_TRANSPORT_GOOD; case 0x01: return USB_STOR_TRANSPORT_FAILED; default: return USB_STOR_TRANSPORT_ERROR; } }