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]; /* 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; }