static inline void mts_debug_dump(struct mts_desc* desc) { MTS_DEBUG("desc at 0x%x: halted = %02x%02x, toggle = %02x%02x\n", (int)desc,(int)desc->usb_dev->halted[1],(int)desc->usb_dev->halted[0], (int)desc->usb_dev->toggle[1],(int)desc->usb_dev->toggle[0] ); MTS_DEBUG("ep_out=%x ep_response=%x ep_image=%x\n", usb_sndbulkpipe(desc->usb_dev,desc->ep_out), usb_rcvbulkpipe(desc->usb_dev,desc->ep_response), usb_rcvbulkpipe(desc->usb_dev,desc->ep_image) ); }
static int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback ) { struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]); int err = 0; int res; MTS_DEBUG_GOT_HERE(); mts_show_command(srb); mts_debug_dump(desc); if ( srb->device->lun || srb->device->id || srb->device->channel ) { MTS_DEBUG("Command to LUN=%d ID=%d CHANNEL=%d from SCSI layer\n",(int)srb->device->lun,(int)srb->device->id, (int)srb->device->channel ); MTS_DEBUG("this device doesn't exist\n"); srb->result = DID_BAD_TARGET << 16; if(callback) callback(srb); goto out; } FILL_BULK_URB(&desc->urb, desc->usb_dev, usb_sndbulkpipe(desc->usb_dev,desc->ep_out), srb->cmnd, srb->cmd_len, mts_command_done, &desc->context ); mts_build_transfer_context( srb, desc ); desc->context.final_callback = callback; res=usb_submit_urb(&desc->urb); if(res){ MTS_ERROR("error %d submitting URB\n",(int)res); srb->result = DID_ERROR << 16; if(callback) callback(srb); } out: return err; }
static int mts_scsi_queuecommand_lck(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback) { struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); int err = 0; int res; MTS_DEBUG_GOT_HERE(); mts_show_command(srb); mts_debug_dump(desc); if ( srb->device->lun || srb->device->id || srb->device->channel ) { MTS_DEBUG("Command to LUN=%d ID=%d CHANNEL=%d from SCSI layer\n",(int)srb->device->lun,(int)srb->device->id, (int)srb->device->channel ); MTS_DEBUG("this device doesn't exist\n"); srb->result = DID_BAD_TARGET << 16; if(likely(callback != NULL)) callback(srb); goto out; } usb_fill_bulk_urb(desc->urb, desc->usb_dev, usb_sndbulkpipe(desc->usb_dev,desc->ep_out), srb->cmnd, srb->cmd_len, mts_command_done, &desc->context ); mts_build_transfer_context( srb, desc ); desc->context.final_callback = callback; /* here we need ATOMIC as we are called with the iolock */ res=usb_submit_urb(desc->urb, GFP_ATOMIC); if(unlikely(res)){ MTS_ERROR("error %d submitting URB\n",(int)res); srb->result = DID_ERROR << 16; if(likely(callback != NULL)) callback(srb); } out: return err; }
static void mts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc ) { int pipe; struct scatterlist * sg; MTS_DEBUG_GOT_HERE(); desc->context.instance = desc; desc->context.srb = srb; desc->context.fragment = 0; if (!srb->use_sg) { if ( !srb->bufflen ){ desc->context.data = 0; desc->context.data_length = 0; return; } else { desc->context.data = srb->buffer; desc->context.data_length = srb->bufflen; MTS_DEBUG("length = %d or %d\n", srb->request_bufflen, srb->bufflen); } } else { MTS_DEBUG("Using scatter/gather\n"); sg = srb->buffer; desc->context.data = sg[0].address; desc->context.data_length = sg[0].length; } /* can't rely on srb->sc_data_direction */ /* Brutally ripped from usb-storage */ if ( !memcmp( srb->cmnd, mts_read_image_sig, mts_read_image_sig_len ) ) { pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_image); MTS_DEBUG( "transfering from desc->ep_image == %d\n", (int)desc->ep_image ); } else if ( MTS_DIRECTION_IS_IN(srb->cmnd[0]) ) { pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_response); MTS_DEBUG( "transfering from desc->ep_response == %d\n", (int)desc->ep_response); } else { MTS_DEBUG("transfering to desc->ep_out == %d\n", (int)desc->ep_out); pipe = usb_sndbulkpipe(desc->usb_dev,desc->ep_out); } desc->context.data_pipe = pipe; }
static void mts_remove_nolock( struct mts_desc* to_remove ) { MTS_DEBUG( "removing 0x%x from list\n", (int)to_remove ); lock_kernel(); mts_urb_abort(to_remove); MTS_DEBUG_GOT_HERE(); if ( to_remove != mts_list ) { MTS_DEBUG_GOT_HERE(); if (to_remove->prev && to_remove->next) to_remove->prev->next = to_remove->next; } else { MTS_DEBUG_GOT_HERE(); mts_list = to_remove->next; if (mts_list) { MTS_DEBUG_GOT_HERE(); mts_list->prev = 0; } } if ( to_remove->next ) { MTS_DEBUG_GOT_HERE(); to_remove->next->prev = to_remove->prev; } MTS_DEBUG_GOT_HERE(); scsi_unregister_host(&to_remove->ctempl); unlock_kernel(); kfree( to_remove ); }
static void mts_remove_nolock( struct mts_desc* to_remove ) { MTS_DEBUG( "removing 0x%x from list\n", (int)to_remove ); mts_wait_abort(to_remove); down( &to_remove->lock ); MTS_DEBUG_GOT_HERE(); if ( to_remove != mts_list ) { MTS_DEBUG_GOT_HERE(); if (to_remove->prev && to_remove->next) to_remove->prev->next = to_remove->next; } else { MTS_DEBUG_GOT_HERE(); mts_list = to_remove->next; if (mts_list) { MTS_DEBUG_GOT_HERE(); mts_list->prev = 0; } } if ( to_remove->next ) { MTS_DEBUG_GOT_HERE(); to_remove->next->prev = to_remove->prev; } MTS_DEBUG_GOT_HERE(); scsi_unregister_module(MODULE_SCSI_HA, &(to_remove->ctempl)); kfree( to_remove ); }
int __init microtek_drv_init(void) { int result; MTS_DEBUG_GOT_HERE(); init_MUTEX(&mts_list_semaphore); if ((result = usb_register(&mts_usb_driver)) < 0) { MTS_DEBUG("usb_register returned %d\n", result ); return -1; } else { MTS_DEBUG("driver registered.\n"); } return 0; }
static void mts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc ) { int pipe; MTS_DEBUG_GOT_HERE(); desc->context.instance = desc; desc->context.srb = srb; desc->context.state = mts_con_command; atomic_set(&desc->context.do_abort,0); if ( !srb->bufflen ){ desc->context.data = 0; desc->context.data_length = 0; return; } else { desc->context.data = srb->buffer; desc->context.data_length = srb->bufflen; } /* can't rely on srb->sc_data_direction */ /* Brutally ripped from usb-storage */ if ( !memcmp( srb->cmnd, mts_read_image_sig, mts_read_image_sig_len ) ) { pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_image); MTS_DEBUG( "transfering from desc->ep_image == %d\n", (int)desc->ep_image ); } else if ( MTS_DIRECTION_IS_IN(srb->cmnd[0]) ) { pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_response); MTS_DEBUG( "transfering from desc->ep_response == %d\n", (int)desc->ep_response); } else { MTS_DEBUG("transfering to desc->ep_out == %d\n", (int)desc->ep_out); pipe = usb_sndbulkpipe(desc->usb_dev,desc->ep_out); } desc->context.data_pipe = pipe; }
static void mts_build_transfer_context(struct scsi_cmnd *srb, struct mts_desc* desc) { int pipe; struct scatterlist * sg; MTS_DEBUG_GOT_HERE(); desc->context.instance = desc; desc->context.srb = srb; desc->context.fragment = 0; if (!scsi_bufflen(srb)) { desc->context.data = NULL; desc->context.data_length = 0; return; } else { sg = scsi_sglist(srb); desc->context.data = sg_virt(&sg[0]); desc->context.data_length = sg[0].length; } /* can't rely on srb->sc_data_direction */ /* Brutally ripped from usb-storage */ if ( !memcmp( srb->cmnd, mts_read_image_sig, mts_read_image_sig_len ) ) { pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_image); MTS_DEBUG( "transfering from desc->ep_image == %d\n", (int)desc->ep_image ); } else if ( MTS_DIRECTION_IS_IN(srb->cmnd[0]) ) { pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_response); MTS_DEBUG( "transfering from desc->ep_response == %d\n", (int)desc->ep_response); } else { MTS_DEBUG("transfering to desc->ep_out == %d\n", (int)desc->ep_out); pipe = usb_sndbulkpipe(desc->usb_dev,desc->ep_out); } desc->context.data_pipe = pipe; }
static void mts_add_nolock( struct mts_desc* to_add ) { MTS_DEBUG( "adding 0x%x to list\n", (int)to_add ); to_add->prev = 0; to_add->next = mts_list; if ( mts_list ) { mts_list->prev = to_add; } mts_list = to_add; }
static void mts_do_sg (struct urb* transfer) { struct scatterlist * sg; MTS_INT_INIT(); MTS_DEBUG("Processing fragment %d of %d\n", context->fragment,context->srb->use_sg); if (transfer->status) { context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16; mts_transfer_cleanup(transfer); } sg = context->srb->buffer; context->fragment++; mts_int_submit_urb(transfer, context->data_pipe, sg[context->fragment].address, sg[context->fragment].length, context->fragment + 1 == context->srb->use_sg ? mts_data_done : mts_do_sg); return; }
static void mts_do_sg (struct urb* transfer) { struct scatterlist * sg; int status = transfer->status; MTS_INT_INIT(); MTS_DEBUG("Processing fragment %d of %d\n", context->fragment, scsi_sg_count(context->srb)); if (unlikely(status)) { context->srb->result = (status == -ENOENT ? DID_ABORT : DID_ERROR)<<16; mts_transfer_cleanup(transfer); } sg = scsi_sglist(context->srb); context->fragment++; mts_int_submit_urb(transfer, context->data_pipe, sg_virt(&sg[context->fragment]), sg[context->fragment].length, context->fragment + 1 == scsi_sg_count(context->srb) ? mts_data_done : mts_do_sg); }
static void * mts_usb_probe (struct usb_device *dev, unsigned int interface, const struct usb_device_id *id) { int i; int result; int ep_out = -1; int ep_in_set[3]; /* this will break if we have more than three endpoints which is why we check */ int *ep_in_current = ep_in_set; struct mts_desc * new_desc; struct vendor_product const* p; /* the altsettting 0 on the interface we're probing */ struct usb_interface_descriptor *altsetting; MTS_DEBUG_GOT_HERE(); MTS_DEBUG( "usb-device descriptor at %x\n", (int)dev ); MTS_DEBUG( "product id = 0x%x, vendor id = 0x%x\n", (int)dev->descriptor.idProduct, (int)dev->descriptor.idVendor ); MTS_DEBUG_GOT_HERE(); p = &mts_supported_products[id - mts_usb_ids]; MTS_DEBUG_GOT_HERE(); MTS_DEBUG( "found model %s\n", p->name ); if ( p->support_status != mts_sup_full ) MTS_MESSAGE( "model %s is not known to be fully supported, reports welcome!\n", p->name ); /* the altsettting 0 on the interface we're probing */ altsetting = &(dev->actconfig->interface[interface].altsetting[0]); /* Check if the config is sane */ if ( altsetting->bNumEndpoints != MTS_EP_TOTAL ) { MTS_WARNING( "expecting %d got %d endpoints! Bailing out.\n", (int)MTS_EP_TOTAL, (int)altsetting->bNumEndpoints ); return NULL; } for( i = 0; i < altsetting->bNumEndpoints; i++ ) { if ((altsetting->endpoint[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) { MTS_WARNING( "can only deal with bulk endpoints; endpoint %d is not bulk.\n", (int)altsetting->endpoint[i].bEndpointAddress ); } else { if (altsetting->endpoint[i].bEndpointAddress & USB_DIR_IN) *ep_in_current++ = altsetting->endpoint[i].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; else { if ( ep_out != -1 ) { MTS_WARNING( "can only deal with one output endpoints. Bailing out." ); return NULL; } ep_out = altsetting->endpoint[i].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; } } } if ( ep_out == -1 ) { MTS_WARNING( "couldn't find an output bulk endpoint. Bailing out.\n" ); return NULL; } /* I don't understand the following fully (it's from usb-storage) -- John */ /* set the interface -- STALL is an acceptable response here */ result = usb_set_interface(dev, altsetting->bInterfaceNumber, 0); MTS_DEBUG("usb_set_interface returned %d.\n",result); switch( result ) { case 0: /* no error */ break; case -EPIPE: usb_clear_halt(dev, usb_sndctrlpipe(dev, 0)); MTS_DEBUG( "clearing clearing stall on control interface\n" ); break; default: MTS_DEBUG( "unknown error %d from usb_set_interface\n", (int)result ); return NULL; } /* allocating a new descriptor */ new_desc = (struct mts_desc *)kmalloc(sizeof(struct mts_desc), GFP_KERNEL); if (new_desc == NULL) { MTS_ERROR("couldn't allocate scanner desc, bailing out!\n"); return NULL; } /* As done by usb_alloc_urb */ memset( new_desc, 0, sizeof(*new_desc) ); spin_lock_init(&new_desc->urb.lock); /* initialising that descriptor */ new_desc->usb_dev = dev; new_desc->interface = interface; init_MUTEX(&new_desc->lock); if(mts_list){ new_desc->host_number = mts_list->host_number+1; } else { new_desc->host_number = 0; } /* endpoints */ new_desc->ep_out = ep_out; new_desc->ep_response = ep_in_set[0]; new_desc->ep_image = ep_in_set[1]; if ( new_desc->ep_out != MTS_EP_OUT ) MTS_WARNING( "will this work? Command EP is not usually %d\n", (int)new_desc->ep_out ); if ( new_desc->ep_response != MTS_EP_RESPONSE ) MTS_WARNING( "will this work? Response EP is not usually %d\n", (int)new_desc->ep_response ); if ( new_desc->ep_image != MTS_EP_IMAGE ) MTS_WARNING( "will this work? Image data EP is not usually %d\n", (int)new_desc->ep_image ); /* Initialize the host template based on the default one */ memcpy(&(new_desc->ctempl), &mts_scsi_host_template, sizeof(mts_scsi_host_template)); /* HACK from usb-storage - this is needed for scsi detection */ (struct mts_desc *)new_desc->ctempl.proc_dir = new_desc; /* FIXME */ MTS_DEBUG("registering SCSI module\n"); new_desc->ctempl.module = THIS_MODULE; result = scsi_register_host(&new_desc->ctempl); /* Will get hit back in microtek_detect by this func */ if ( result ) { MTS_ERROR( "error %d from scsi_register_host! Help!\n", (int)result ); /* FIXME: need more cleanup? */ kfree( new_desc ); return NULL; } MTS_DEBUG_GOT_HERE(); /* FIXME: the bomb is armed, must the host be registered under lock ? */ /* join the list - lock it */ down(&mts_list_semaphore); mts_add_nolock( new_desc ); up(&mts_list_semaphore); MTS_DEBUG("completed probe and exiting happily\n"); return (void *)new_desc; }
static inline void mts_show_command(Scsi_Cmnd *srb) { char *what = NULL; switch (srb->cmnd[0]) { case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break; case REZERO_UNIT: what = "REZERO_UNIT"; break; case REQUEST_SENSE: what = "REQUEST_SENSE"; break; case FORMAT_UNIT: what = "FORMAT_UNIT"; break; case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break; case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break; case READ_6: what = "READ_6"; break; case WRITE_6: what = "WRITE_6"; break; case SEEK_6: what = "SEEK_6"; break; case READ_REVERSE: what = "READ_REVERSE"; break; case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break; case SPACE: what = "SPACE"; break; case INQUIRY: what = "INQUIRY"; break; case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break; case MODE_SELECT: what = "MODE_SELECT"; break; case RESERVE: what = "RESERVE"; break; case RELEASE: what = "RELEASE"; break; case COPY: what = "COPY"; break; case ERASE: what = "ERASE"; break; case MODE_SENSE: what = "MODE_SENSE"; break; case START_STOP: what = "START_STOP"; break; case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break; case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break; case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break; case SET_WINDOW: what = "SET_WINDOW"; break; case READ_CAPACITY: what = "READ_CAPACITY"; break; case READ_10: what = "READ_10"; break; case WRITE_10: what = "WRITE_10"; break; case SEEK_10: what = "SEEK_10"; break; case WRITE_VERIFY: what = "WRITE_VERIFY"; break; case VERIFY: what = "VERIFY"; break; case SEARCH_HIGH: what = "SEARCH_HIGH"; break; case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break; case SEARCH_LOW: what = "SEARCH_LOW"; break; case SET_LIMITS: what = "SET_LIMITS"; break; case READ_POSITION: what = "READ_POSITION"; break; case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break; case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break; case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break; case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break; case COMPARE: what = "COMPARE"; break; case COPY_VERIFY: what = "COPY_VERIFY"; break; case WRITE_BUFFER: what = "WRITE_BUFFER"; break; case READ_BUFFER: what = "READ_BUFFER"; break; case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break; case READ_LONG: what = "READ_LONG"; break; case WRITE_LONG: what = "WRITE_LONG"; break; case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break; case WRITE_SAME: what = "WRITE_SAME"; break; case READ_TOC: what = "READ_TOC"; break; case LOG_SELECT: what = "LOG_SELECT"; break; case LOG_SENSE: what = "LOG_SENSE"; break; case MODE_SELECT_10: what = "MODE_SELECT_10"; break; case MODE_SENSE_10: what = "MODE_SENSE_10"; break; case MOVE_MEDIUM: what = "MOVE_MEDIUM"; break; case READ_12: what = "READ_12"; break; case WRITE_12: what = "WRITE_12"; break; case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break; case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break; case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break; case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break; case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break; case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break; case WRITE_LONG_2: what = "WRITE_LONG_2"; break; default: MTS_DEBUG("can't decode command\n"); goto out; break; } MTS_DEBUG( "Command %s (%d bytes)\n", what, srb->cmd_len); out: MTS_DEBUG( " %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", srb->cmnd[0], srb->cmnd[1], srb->cmnd[2], srb->cmnd[3], srb->cmnd[4], srb->cmnd[5], srb->cmnd[6], srb->cmnd[7], srb->cmnd[8], srb->cmnd[9]); }
static int mts_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { int i; int ep_out = -1; int ep_in_set[3]; /* this will break if we have more than three endpoints which is why we check */ int *ep_in_current = ep_in_set; int err_retval = -ENOMEM; struct mts_desc * new_desc; struct vendor_product const* p; struct usb_device *dev = interface_to_usbdev (intf); /* the current altsetting on the interface we're probing */ struct usb_host_interface *altsetting; MTS_DEBUG_GOT_HERE(); MTS_DEBUG( "usb-device descriptor at %x\n", (int)dev ); MTS_DEBUG( "product id = 0x%x, vendor id = 0x%x\n", le16_to_cpu(dev->descriptor.idProduct), le16_to_cpu(dev->descriptor.idVendor) ); MTS_DEBUG_GOT_HERE(); p = &mts_supported_products[id - mts_usb_ids]; MTS_DEBUG_GOT_HERE(); MTS_DEBUG( "found model %s\n", p->name ); if ( p->support_status != mts_sup_full ) MTS_MESSAGE( "model %s is not known to be fully supported, reports welcome!\n", p->name ); /* the current altsetting on the interface we're probing */ altsetting = intf->cur_altsetting; /* Check if the config is sane */ if ( altsetting->desc.bNumEndpoints != MTS_EP_TOTAL ) { MTS_WARNING( "expecting %d got %d endpoints! Bailing out.\n", (int)MTS_EP_TOTAL, (int)altsetting->desc.bNumEndpoints ); return -ENODEV; } for( i = 0; i < altsetting->desc.bNumEndpoints; i++ ) { if ((altsetting->endpoint[i].desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) { MTS_WARNING( "can only deal with bulk endpoints; endpoint %d is not bulk.\n", (int)altsetting->endpoint[i].desc.bEndpointAddress ); } else { if (altsetting->endpoint[i].desc.bEndpointAddress & USB_DIR_IN) *ep_in_current++ = altsetting->endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; else { if ( ep_out != -1 ) { MTS_WARNING( "can only deal with one output endpoints. Bailing out." ); return -ENODEV; } ep_out = altsetting->endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; } } } if ( ep_out == -1 ) { MTS_WARNING( "couldn't find an output bulk endpoint. Bailing out.\n" ); return -ENODEV; } new_desc = kzalloc(sizeof(struct mts_desc), GFP_KERNEL); if (!new_desc) goto out; new_desc->urb = usb_alloc_urb(0, GFP_KERNEL); if (!new_desc->urb) goto out_kfree; new_desc->context.scsi_status = kmalloc(1, GFP_KERNEL); if (!new_desc->context.scsi_status) goto out_kfree2; new_desc->usb_dev = dev; new_desc->usb_intf = intf; init_MUTEX(&new_desc->lock); /* endpoints */ new_desc->ep_out = ep_out; new_desc->ep_response = ep_in_set[0]; new_desc->ep_image = ep_in_set[1]; if ( new_desc->ep_out != MTS_EP_OUT ) MTS_WARNING( "will this work? Command EP is not usually %d\n", (int)new_desc->ep_out ); if ( new_desc->ep_response != MTS_EP_RESPONSE ) MTS_WARNING( "will this work? Response EP is not usually %d\n", (int)new_desc->ep_response ); if ( new_desc->ep_image != MTS_EP_IMAGE ) MTS_WARNING( "will this work? Image data EP is not usually %d\n", (int)new_desc->ep_image ); new_desc->host = scsi_host_alloc(&mts_scsi_host_template, sizeof(new_desc)); if (!new_desc->host) goto out_free_urb; new_desc->host->hostdata[0] = (unsigned long)new_desc; if (scsi_add_host(new_desc->host, NULL)) { err_retval = -EIO; goto out_free_urb; } scsi_scan_host(new_desc->host); usb_set_intfdata(intf, new_desc); return 0; out_kfree2: kfree(new_desc->context.scsi_status); out_free_urb: usb_free_urb(new_desc->urb); out_kfree: kfree(new_desc); out: return err_retval; }
static int mts_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { int i; int ep_out = -1; int ep_in_set[3]; int *ep_in_current = ep_in_set; int err_retval = -ENOMEM; struct mts_desc * new_desc; struct usb_device *dev = interface_to_usbdev (intf); struct usb_host_interface *altsetting; MTS_DEBUG_GOT_HERE(); MTS_DEBUG( "usb-device descriptor at %x\n", (int)dev ); MTS_DEBUG( "product id = 0x%x, vendor id = 0x%x\n", le16_to_cpu(dev->descriptor.idProduct), le16_to_cpu(dev->descriptor.idVendor) ); MTS_DEBUG_GOT_HERE(); altsetting = intf->cur_altsetting; if ( altsetting->desc.bNumEndpoints != MTS_EP_TOTAL ) { MTS_WARNING( "expecting %d got %d endpoints! Bailing out.\n", (int)MTS_EP_TOTAL, (int)altsetting->desc.bNumEndpoints ); return -ENODEV; } for( i = 0; i < altsetting->desc.bNumEndpoints; i++ ) { if ((altsetting->endpoint[i].desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) { MTS_WARNING( "can only deal with bulk endpoints; endpoint %d is not bulk.\n", (int)altsetting->endpoint[i].desc.bEndpointAddress ); } else { if (altsetting->endpoint[i].desc.bEndpointAddress & USB_DIR_IN) *ep_in_current++ = altsetting->endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; else { if ( ep_out != -1 ) { MTS_WARNING( "can only deal with one output endpoints. Bailing out." ); return -ENODEV; } ep_out = altsetting->endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; } } } if ( ep_out == -1 ) { MTS_WARNING( "couldn't find an output bulk endpoint. Bailing out.\n" ); return -ENODEV; } new_desc = kzalloc(sizeof(struct mts_desc), GFP_KERNEL); if (!new_desc) goto out; new_desc->urb = usb_alloc_urb(0, GFP_KERNEL); if (!new_desc->urb) goto out_kfree; new_desc->context.scsi_status = kmalloc(1, GFP_KERNEL); if (!new_desc->context.scsi_status) goto out_free_urb; new_desc->usb_dev = dev; new_desc->usb_intf = intf; new_desc->ep_out = ep_out; new_desc->ep_response = ep_in_set[0]; new_desc->ep_image = ep_in_set[1]; if ( new_desc->ep_out != MTS_EP_OUT ) MTS_WARNING( "will this work? Command EP is not usually %d\n", (int)new_desc->ep_out ); if ( new_desc->ep_response != MTS_EP_RESPONSE ) MTS_WARNING( "will this work? Response EP is not usually %d\n", (int)new_desc->ep_response ); if ( new_desc->ep_image != MTS_EP_IMAGE ) MTS_WARNING( "will this work? Image data EP is not usually %d\n", (int)new_desc->ep_image ); new_desc->host = scsi_host_alloc(&mts_scsi_host_template, sizeof(new_desc)); if (!new_desc->host) goto out_kfree2; new_desc->host->hostdata[0] = (unsigned long)new_desc; if (scsi_add_host(new_desc->host, &dev->dev)) { err_retval = -EIO; goto out_host_put; } scsi_scan_host(new_desc->host); usb_set_intfdata(intf, new_desc); return 0; out_host_put: scsi_host_put(new_desc->host); out_kfree2: kfree(new_desc->context.scsi_status); out_free_urb: usb_free_urb(new_desc->urb); out_kfree: kfree(new_desc); out: return err_retval; }