/* did an abort occur during the submission? */ if (test_bit(US_FLIDX_ABORTING, &us->dflags)) {
/* cancel the URB, if it hasn't been cancelled already */ if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
usb_stor_dbg(us, "-- cancelling URB\n");
usb_unlink_urb(us->current_urb);
}
}
/* wait for the completion of the URB */
timeleft = wait_for_completion_interruptible_timeout(
&urb_done, timeout ? : MAX_SCHEDULE_TIMEOUT);
/* fill in the devrequest structure */
us->cr->bRequestType = requesttype;
us->cr->bRequest = request;
us->cr->wValue = cpu_to_le16(value);
us->cr->wIndex = cpu_to_le16(index);
us->cr->wLength = cpu_to_le16(size);
/* fill and submit the URB */
usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe,
(unsignedchar*) us->cr, data, size,
usb_stor_blocking_completion, NULL);
status = usb_stor_msg_common(us, timeout);
/* return the actual length of the data transferred if no error */ if (status == 0)
status = us->current_urb->actual_length; return status;
}
EXPORT_SYMBOL_GPL(usb_stor_control_msg);
/* *Thisisaversionofusb_clear_halt()thatallowsearlyterminationand *doesn'treadthestatusfromthedevice--thisisbecausesomedevices *crashtheirinternalfirmwarewhenthestatusisrequestedafterahalt. * *Adefinitivelistofthese'bad'devicesistoodifficulttomaintainor *makecompleteenoughtobeuseful.Thisproblemwasfirstobservedonthe *HagiwaraFlashGateDUALunit.However,bustracesrevealthatneither *MacOSnorWindowschecksthestatusafterclearingahalt. * *Sincemanyvendorsinthisspacelimittheirtestingtointeroperability *withthesetwoOSes,specificationviolationslikethisonearecommon.
*/ int usb_stor_clear_halt(struct us_data *us, unsignedint pipe)
{ int result; int endp = usb_pipeendpoint(pipe);
/* no error code; did we send all the data? */ case0: if (partial != length) {
usb_stor_dbg(us, "-- short transfer\n"); return USB_STOR_XFER_SHORT;
}
usb_stor_dbg(us, "-- transfer complete\n"); return USB_STOR_XFER_GOOD;
/* stalled */ case -EPIPE: /* *forcontrolendpoints,(usedbyCB[I])astallindicates *afailedcommand
*/ if (usb_pipecontrol(pipe)) {
usb_stor_dbg(us, "-- stall on control pipe\n"); return USB_STOR_XFER_STALLED;
}
/* for other sorts of endpoint, clear the stall */
usb_stor_dbg(us, "clearing endpoint halt for pipe 0x%x\n",
pipe); if (usb_stor_clear_halt(us, pipe) < 0) return USB_STOR_XFER_ERROR; return USB_STOR_XFER_STALLED;
/* babble - the device tried to send more than we wanted to read */ case -EOVERFLOW:
usb_stor_dbg(us, "-- babble\n"); return USB_STOR_XFER_LONG;
/* the transfer was cancelled by abort, disconnect, or timeout */ case -ECONNRESET:
usb_stor_dbg(us, "-- transfer cancelled\n"); return USB_STOR_XFER_ERROR;
/* short scatter-gather read transfer */ case -EREMOTEIO:
usb_stor_dbg(us, "-- short read transfer\n"); return USB_STOR_XFER_SHORT;
/* abort or disconnect in progress */ case -EIO:
usb_stor_dbg(us, "-- abort or disconnect in progress\n"); return USB_STOR_XFER_ERROR;
/* the catch-all error case */ default:
usb_stor_dbg(us, "-- unknown error\n"); return USB_STOR_XFER_ERROR;
}
}
/* fill in the devrequest structure */
us->cr->bRequestType = requesttype;
us->cr->bRequest = request;
us->cr->wValue = cpu_to_le16(value);
us->cr->wIndex = cpu_to_le16(index);
us->cr->wLength = cpu_to_le16(size);
/* fill and submit the URB */
usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe,
(unsignedchar*) us->cr, data, size,
usb_stor_blocking_completion, NULL);
result = usb_stor_msg_common(us, 0);
/* calculate the max packet size */
maxp = usb_maxpacket(us->pusb_dev, pipe); if (maxp > length)
maxp = length;
/* fill and submit the URB */
usb_fill_int_urb(us->current_urb, us->pusb_dev, pipe, buf,
maxp, usb_stor_blocking_completion, NULL,
us->ep_bInterval);
result = usb_stor_msg_common(us, 0);
/* *Transferonebufferviabulkpipe,withouttimeouts,butallowingearly *termination.ReturncodesareUSB_STOR_XFER_xxx.Ifthebulkpipe *stallsduringthetransfer,thehaltisautomaticallycleared.
*/ int usb_stor_bulk_transfer_buf(struct us_data *us, unsignedint pipe, void *buf, unsignedint length, unsignedint *act_len)
{ int result;
usb_stor_dbg(us, "xfer %u bytes\n", length);
/* fill and submit the URB */
usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, buf, length,
usb_stor_blocking_completion, NULL);
result = usb_stor_msg_common(us, 0);
/* store the actual length of the data transferred */ if (act_len)
*act_len = us->current_urb->actual_length; return interpret_urb_result(us, pipe, length, result,
us->current_urb->actual_length);
}
EXPORT_SYMBOL_GPL(usb_stor_bulk_transfer_buf);
/* did an abort occur during the submission? */ if (test_bit(US_FLIDX_ABORTING, &us->dflags)) {
/* cancel the request, if it hasn't been cancelled already */ if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
usb_stor_dbg(us, "-- cancelling sg request\n");
usb_sg_cancel(&us->current_sg);
}
}
/* wait for the completion of the transfer */
usb_sg_wait(&us->current_sg);
clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags);
result = us->current_sg.status; if (act_len)
*act_len = us->current_sg.bytes; return interpret_urb_result(us, pipe, length, result,
us->current_sg.bytes);
usb_stor_xfer_error: if (act_len)
*act_len = 0; return USB_STOR_XFER_ERROR;
}
/* *Commonusedfunction.Transferacompletecommand *viausb_stor_bulk_transfer_sglist()above.Setcmndresid
*/ int usb_stor_bulk_srb(struct us_data* us, unsignedint pipe, struct scsi_cmnd* srb)
{ unsignedint partial; int result = usb_stor_bulk_transfer_sglist(us, pipe, scsi_sglist(srb),
scsi_sg_count(srb), scsi_bufflen(srb),
&partial);
/* *TransferanentireSCSIcommand'sworthofdatapayloadoverthebulk *pipe. * *Notethatthisusesusb_stor_bulk_transfer_buf()and *usb_stor_bulk_transfer_sglist()toachieveitsgoals-- *thisfunctionsimplydetermineswhetherwe'regoingtouse *scatter-gatherornot,andactsappropriately.
*/ int usb_stor_bulk_transfer_sg(struct us_data* us, unsignedint pipe, void *buf, unsignedint length_left, int use_sg, int *residual)
{ int result; unsignedint partial;
/* are we scatter-gathering? */ if (use_sg) { /* use the usb core scatter-gather primitives */
result = usb_stor_bulk_transfer_sglist(us, pipe,
(struct scatterlist *) buf, use_sg,
length_left, &partial);
length_left -= partial;
} else { /* no scatter-gather, just make the request */
result = usb_stor_bulk_transfer_buf(us, pipe, buf,
length_left, &partial);
length_left -= partial;
}
/* store the residual and return the error code */ if (residual)
*residual = length_left; return result;
}
EXPORT_SYMBOL_GPL(usb_stor_bulk_transfer_sg);
/* if there is a transport error, reset and don't auto-sense */ if (result == USB_STOR_TRANSPORT_ERROR) {
usb_stor_dbg(us, "-- transport indicates error, resetting\n");
srb->result = DID_ERROR << 16; goto Handle_Errors;
}
/* if the transport provided its own sense data, don't auto-sense */ if (result == USB_STOR_TRANSPORT_NO_SENSE) {
srb->result = SAM_STAT_CHECK_CONDITION;
last_sector_hacks(us, srb); return;
}
/* Some devices (Kindle) require another command after SYNC CACHE */ if ((us->fflags & US_FL_SENSE_AFTER_SYNC) &&
srb->cmnd[0] == SYNCHRONIZE_CACHE) {
usb_stor_dbg(us, "-- sense after SYNC CACHE\n");
need_auto_sense = 1;
}
/* *Ifwehaveafailure,we'regoingtodoaREQUEST_SENSE *automatically.Notethatwedifferentiatebetweenacommand *"failure"andan"error"inthetransportmechanism.
*/ if (result == USB_STOR_TRANSPORT_FAILED) {
usb_stor_dbg(us, "-- transport indicates command failure\n");
need_auto_sense = 1;
}
/* Now, if we need to do the auto-sense, let's do it */ if (need_auto_sense) { int temp_result; struct scsi_eh_save ses; int sense_size = US_SENSE_SIZE; struct scsi_sense_hdr sshdr; const u8 *scdd;
u8 fm_ili;
/* device supports and needs bigger sense buffer */ if (us->fflags & US_FL_SANE_SENSE)
sense_size = ~0;
Retry_Sense:
usb_stor_dbg(us, "Issuing auto-REQUEST_SENSE\n");
/* FIXME: we must do the protocol translation here */ if (us->subclass == USB_SC_RBC || us->subclass == USB_SC_SCSI ||
us->subclass == USB_SC_CYP_ATACB)
srb->cmd_len = 6; else
srb->cmd_len = 12;
/* Did we transfer less than the minimum amount required? */ if ((srb->result == SAM_STAT_GOOD || srb->sense_buffer[2] == 0) &&
scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow)
srb->result = DID_ERROR << 16;
/* Stop the current URB transfer */ void usb_stor_stop_transport(struct us_data *us)
{ /* *IfthestatemachineisblockedwaitingforanURB, *let'swakeitup.Thetest_and_clear_bit()call *guaranteesthatifaURBhasjustbeensubmitted, *itwon'tbecancelledmorethanonce.
*/ if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
usb_stor_dbg(us, "-- cancelling URB\n");
usb_unlink_urb(us->current_urb);
}
/* If we are waiting for a scatter-gather operation, cancel it. */ if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
usb_stor_dbg(us, "-- cancelling sg request\n");
usb_sg_cancel(&us->current_sg);
}
}
int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
{ unsignedint transfer_length = scsi_bufflen(srb); unsignedint pipe = 0; int result;
/* COMMAND STAGE */ /* let's send the command via the control pipe */ /* *Commandissometime(f.e.afterscsi_eh_prep_cmnd)onthestack. *Stackmaybevmallocated.SonoDMAforus.Makeacopy.
*/
memcpy(us->iobuf, srb->cmnd, srb->cmd_len);
result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
US_CBI_ADSC,
USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,
us->ifnum, us->iobuf, srb->cmd_len);
/* check the return code for the command */
usb_stor_dbg(us, "Call to usb_stor_ctrl_transfer() returned %d\n",
result);
/* if we stalled the command, it means command failed */ if (result == USB_STOR_XFER_STALLED) { return USB_STOR_TRANSPORT_FAILED;
}
/* Uh oh... serious problem here */ if (result != USB_STOR_XFER_GOOD) { return USB_STOR_TRANSPORT_ERROR;
}
/* DATA STAGE */ /* transfer the data payload for this command, if one exists*/ if (transfer_length) {
pipe = srb->sc_data_direction == DMA_FROM_DEVICE ?
us->recv_bulk_pipe : us->send_bulk_pipe;
result = usb_stor_bulk_srb(us, pipe, srb);
usb_stor_dbg(us, "CBI data stage result is 0x%x\n", result);
/* if we stalled the data transfer it means command failed */ if (result == USB_STOR_XFER_STALLED) return USB_STOR_TRANSPORT_FAILED; if (result > USB_STOR_XFER_STALLED) return USB_STOR_TRANSPORT_ERROR;
}
/* STATUS STAGE */
/* *NOTE:CBdoesnothaveastatusstage.Silly,Iknow.So *wehavetocatchthisatahigherlevel.
*/ if (us->protocol != USB_PR_CBI) return USB_STOR_TRANSPORT_GOOD;
result = usb_stor_intr_transfer(us, us->iobuf, 2);
usb_stor_dbg(us, "Got interrupt data (0x%x, 0x%x)\n",
us->iobuf[0], us->iobuf[1]); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR;
/* *UFIgivesusASCandASCQ,likearequestsense * *REQUEST_SENSEandINQUIRYdon'taffectthesensedataonUFI *devices,soweignoretheinformationforthosecommands.Note *thatthismeanswecouldbeignoringarealerroronthese *commands,butthatcan'tbehelped.
*/ if (us->subclass == USB_SC_UFI) { if (srb->cmnd[0] == REQUEST_SENSE ||
srb->cmnd[0] == INQUIRY) return USB_STOR_TRANSPORT_GOOD; if (us->iobuf[0]) goto Failed; return USB_STOR_TRANSPORT_GOOD;
}
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. */ if (result > 0) { if (us->iobuf[0] <= US_BULK_MAX_LUN_LIMIT) { return us->iobuf[0];
} else {
dev_info(&us->pusb_intf->dev, "Max LUN %d is not valid, using 0 instead",
us->iobuf[0]);
}
}
/* send it to out endpoint */
usb_stor_dbg(us, "Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n",
le32_to_cpu(bcb->Signature), bcb->Tag,
le32_to_cpu(bcb->DataTransferLength), bcb->Flags,
(bcb->Lun >> 4), (bcb->Lun & 0x0F),
bcb->Length);
result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
bcb, cbwlen, NULL);
usb_stor_dbg(us, "Bulk command transfer result=%d\n", result); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR;
/* DATA STAGE */ /* send/receive data payload, if there is any */
/* get CSW for device status */
usb_stor_dbg(us, "Attempting to get CSW...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
bcs, US_BULK_CS_WRAP_LEN, &cswlen);
/* did the attempt to read the CSW fail? */ if (result == USB_STOR_XFER_STALLED) {
/* get the status again */
usb_stor_dbg(us, "Attempting to get CSW (2nd try)...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
bcs, US_BULK_CS_WRAP_LEN, NULL);
}
/* if we still have a failure at this point, we're in trouble */
usb_stor_dbg(us, "Bulk status result = %d\n", result); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR;
skipped_data_phase: /* check bulk status */
residue = le32_to_cpu(bcs->Residue);
usb_stor_dbg(us, "Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
le32_to_cpu(bcs->Signature), bcs->Tag,
residue, bcs->Status); if (!(bcs->Tag == us->tag || (us->fflags & US_FL_BULK_IGNORE_TAG)) ||
bcs->Status > US_BULK_STAT_PHASE) {
usb_stor_dbg(us, "Bulk logical error\n"); return USB_STOR_TRANSPORT_ERROR;
}
/* based on the status code, we report good or bad */ switch (bcs->Status) { case US_BULK_STAT_OK: /* device babbled -- return fake sense data */ if (fake_sense) {
memcpy(srb->sense_buffer,
usb_stor_sense_invalidCDB, sizeof(usb_stor_sense_invalidCDB)); return USB_STOR_TRANSPORT_NO_SENSE;
}
/* command good -- note that data could be short */ return USB_STOR_TRANSPORT_GOOD;
case US_BULK_STAT_FAIL: /* command failed */ return USB_STOR_TRANSPORT_FAILED;
case US_BULK_STAT_PHASE: /* *phaseerror--notethatatransportresetwillbe *invokedbytheinvoke_transport()function
*/ return USB_STOR_TRANSPORT_ERROR;
}
/* we should never get here, but if we do, we're in trouble */ return USB_STOR_TRANSPORT_ERROR;
}
EXPORT_SYMBOL_GPL(usb_stor_Bulk_transport);
/* 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;
}
/* This issues a CB[I] Reset to the device in question */ #define CB_RESET_CMD_SIZE 12
/* *IssueaUSBportresettothedevice.Thecallermustnothold *us->dev_mutex.
*/ int usb_stor_port_reset(struct us_data *us)
{ int result;
/*for these devices we must use the class specific method */ if (us->pusb_dev->quirks & USB_QUIRK_RESET) return -EPERM;
result = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); if (result < 0)
usb_stor_dbg(us, "unable to lock device for reset: %d\n",
result); else { /* Were we disconnected while waiting for the lock? */ if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
result = -EIO;
usb_stor_dbg(us, "No reset during disconnect\n");
} else {
result = usb_reset_device(us->pusb_dev);
usb_stor_dbg(us, "usb_reset_device returns %d\n",
result);
}
usb_unlock_device(us->pusb_dev);
} return result;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.38 Sekunden
(vorverarbeitet am 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.