static void mts_command_done( struct urb *transfer ) /* Interrupt context! */ { MTS_INT_INIT(); if ( transfer->status ) { if (transfer->status == -ENOENT) { /* We are being killed */ MTS_DEBUG_GOT_HERE(); context->srb->result = DID_ABORT<<16; } else { /* A genuine error has occured */ MTS_DEBUG_GOT_HERE(); context->srb->result = DID_ERROR<<16; } mts_transfer_cleanup(transfer); return; } if ( context->data ) { mts_int_submit_urb(transfer, context->data_pipe, context->data, context->data_length, context->srb->use_sg ? mts_do_sg : mts_data_done); } else mts_get_status(transfer); return; }
static inline void mts_urb_abort(struct mts_desc* desc) { MTS_DEBUG_GOT_HERE(); mts_debug_dump(desc); if ( desc->urb.status == USB_ST_URB_PENDING ) { usb_unlink_urb( &desc->urb ); } }
static int mts_scsi_detect (struct SHT * sht) { /* Whole function stolen from usb-storage */ struct mts_desc * desc = (struct mts_desc *)sht->proc_dir; /* What a hideous hack! */ char local_name[48]; MTS_DEBUG_GOT_HERE(); /* set up the name of our subdirectory under /proc/scsi/ */ sprintf(local_name, "microtek-%d", desc->host_number); sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_KERNEL); /* FIXME: where is this freed ? */ if (!sht->proc_name) { MTS_ERROR( "unable to allocate memory for proc interface!!\n" ); return 0; } strcpy(sht->proc_name, local_name); sht->proc_dir = NULL; /* In host->hostdata we store a pointer to desc */ desc->host = scsi_register(sht, sizeof(desc)); desc->host->hostdata[0] = (unsigned long)desc; /* FIXME: what if sizeof(void*) != sizeof(unsigned long)? */ return 1; }
static inline void mts_urb_abort(struct mts_desc* desc) { spin_unlock_irq(&io_request_lock); MTS_DEBUG_GOT_HERE(); mts_debug_dump(desc); usb_unlink_urb( &desc->urb ); spin_lock_irq(&io_request_lock); }
static int mts_scsi_abort (Scsi_Cmnd *srb) { struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); MTS_DEBUG_GOT_HERE(); mts_urb_abort(desc); return FAILED; }
static int mts_scsi_host_reset (Scsi_Cmnd *srb) { struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]); MTS_DEBUG_GOT_HERE(); mts_debug_dump(desc); usb_reset_device(desc->usb_dev); /*FIXME: untested on new reset code */ return 0; /* RANT why here 0 and not SUCCESS */ }
static int mts_scsi_abort (Scsi_Cmnd *srb) { struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]); MTS_DEBUG_GOT_HERE(); mts_urb_abort(desc); return SCSI_ABORT_PENDING; }
static void mts_command_done( struct urb *transfer ) /* Interrupt context! */ { int status = transfer->status; MTS_INT_INIT(); if ( unlikely(status) ) { if (status == -ENOENT) { /* We are being killed */ MTS_DEBUG_GOT_HERE(); context->srb->result = DID_ABORT<<16; } else { /* A genuine error has occurred */ MTS_DEBUG_GOT_HERE(); context->srb->result = DID_ERROR<<16; } mts_transfer_cleanup(transfer); return; } if (context->srb->cmnd[0] == REQUEST_SENSE) { mts_int_submit_urb(transfer, context->data_pipe, context->srb->sense_buffer, context->data_length, mts_data_done); } else { if ( context->data ) { mts_int_submit_urb(transfer, context->data_pipe, context->data, context->data_length, scsi_sg_count(context->srb) > 1 ? mts_do_sg : mts_data_done); } else { mts_get_status(transfer); } } return; }
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 inline void mts_wait_abort(struct mts_desc* desc) { mts_request_abort(desc); while( !atomic_read(&desc->lock.count) ) { /* Is there a function to check if the semaphore is locked? */ schedule_timeout( MTS_ABORT_TIMEOUT ); MTS_DEBUG_GOT_HERE(); mts_urb_abort(desc); } }
static int mts_scsi_abort (Scsi_Cmnd *srb) /* interrupt context (!) */ /* FIXME this is about to become task context */ { struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]); MTS_DEBUG_GOT_HERE(); mts_request_abort(desc); mts_urb_abort(desc); return SCSI_ABORT_PENDING; }
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 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 ); }
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_usb_disconnect (struct usb_device *dev, void *ptr) { struct mts_desc* to_remove = (struct mts_desc*)ptr; MTS_DEBUG_GOT_HERE(); /* leave the list - lock it */ down(&mts_list_semaphore); mts_remove_nolock(to_remove); up(&mts_list_semaphore); }
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 int mts_scsi_host_reset(struct scsi_cmnd *srb) { struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); int result; MTS_DEBUG_GOT_HERE(); mts_debug_dump(desc); result = usb_lock_device_for_reset(desc->usb_dev, desc->usb_intf); if (result == 0) { result = usb_reset_device(desc->usb_dev); usb_unlock_device(desc->usb_dev); } return result ? FAILED : SUCCESS; }
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_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
void __exit microtek_drv_exit(void) { struct mts_desc* next; MTS_DEBUG_GOT_HERE(); usb_deregister(&mts_usb_driver); down(&mts_list_semaphore); while (mts_list) { /* keep track of where the next one is */ next = mts_list->next; mts_remove_nolock( mts_list ); /* advance the list pointer */ mts_list = next; } up(&mts_list_semaphore); }
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 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; }
static inline void mts_request_abort(struct mts_desc* desc) { MTS_DEBUG_GOT_HERE(); mts_debug_dump(desc); atomic_set(&desc->context.do_abort,1); }
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_scsi_release(struct Scsi_Host *psh) { MTS_DEBUG_GOT_HERE(); return 0; }
static inline void mts_urb_abort(struct mts_desc* desc) { MTS_DEBUG_GOT_HERE(); mts_debug_dump(desc); usb_unlink_urb( &desc->urb ); }