static s32 __usbstorage_reset(usbstorage_handle *dev)
{
	s32 retval;
    
    /*
     retval = ehci_reset_device(dev->usb_fd);
     if(retval < 0 && retval != -7004)
     goto end;
     */
    //debug_printf("usbstorage reset..\n");
    USB_LOG("Resetting device.\n");
	retval = __USB_CtrlMsgTimeout(dev, (USB_CTRLTYPE_DIR_HOST2DEVICE | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_RESET, 0, dev->interface, 0, NULL);
    
	/* FIXME?: some devices return -7004 here which definitely violates the usb ms protocol but they still seem to be working... */
	if(retval < 0 && retval != -7004)
		goto end;
    
	/* gives device enough time to process the reset */
	usleep(10);
    
    USB_LOG("Clearing halts on both endpoints\n");
    //debug_printf("cleat halt on bulk ep..\n");
    
    retval = (*context.interface)->ClearPipeStallBothEnds(context.interface, dev->ep_in);
    if(retval < 0)
		goto end;
	retval = (*context.interface)->ClearPipeStallBothEnds(context.interface, dev->ep_out);
    
end:
	return retval;
}
Exemple #2
0
static s32 __usbstorage_reset(usbstorage_handle *dev)
{
	s32 retval;

	if(dev->suspended == 1)
	{
		USB_ResumeDevice(dev->usb_fd);
		dev->suspended = 0;
	}
/*  
      retval = ehci_reset_device(dev->usb_fd);
	if(retval < 0 && retval != -7004)
		goto end;
  */              
        //debug_printf("usbstorage reset..\n");
	retval = __USB_CtrlMsgTimeout(dev, (USB_CTRLTYPE_DIR_HOST2DEVICE | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_RESET, 0, dev->interface, 0, NULL);

	/* FIXME?: some devices return -7004 here which definitely violates the usb ms protocol but they still seem to be working... */
	if(retval < 0 && retval != -7004)
		goto end;

	/* gives device enough time to process the reset */
	msleep(10);

        //debug_printf("cleat halt on bulk ep..\n");
	retval = USB_ClearHalt(dev->usb_fd, dev->ep_in);
	if(retval < 0)
		goto end;
	retval = USB_ClearHalt(dev->usb_fd, dev->ep_out);

end:
	return retval;
}
Exemple #3
0
static s32 __usbstorage_reset(usbstorage_handle *dev)
{
	u32 t = usbtimeout;
	usbtimeout = 1;
	s32 retval = __USB_CtrlMsgTimeout(dev, (USB_CTRLTYPE_DIR_HOST2DEVICE | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_RESET, 0, dev->interface, 0, NULL);
	usbtimeout = t;
	usleep(60*1000);
	USB_OGC_ClearHalt(dev->usb_fd, dev->ep_in);usleep(10000); //from http://www.usb.org/developers/devclass_docs/usbmassbulk_10.pdf
	USB_OGC_ClearHalt(dev->usb_fd, dev->ep_out);usleep(10000);
	return retval;
}
Exemple #4
0
s32 USBStorageOGC_Open(usbstorage_handle *dev, s32 device_id, u16 vid, u16 pid)
{
	s32 retval = -1;
	u8 conf = -1;
	u8 *max_lun;
	u32 iConf, iInterface, iEp;
	usb_devdesc udd;
	usb_configurationdesc *ucd;
	usb_interfacedesc *uid;
	usb_endpointdesc *ued;

	max_lun = __lwp_heap_allocate(&__heap, 1);
	if (!max_lun)
		return IPC_ENOMEM;

	memset(dev, 0, sizeof(*dev));
	dev->usb_fd = -1;

	dev->tag = TAG_START;

	if (LWP_MutexInit(&dev->lock, false) < 0)
		goto free_and_return;

	if (SYS_CreateAlarm(&dev->alarm) < 0)
		goto free_and_return;

	retval = USB_OGC_OpenDevice(device_id, vid, pid, &dev->usb_fd);
	if (retval < 0)
		goto free_and_return;

	retval = USB_OGC_GetDescriptors(dev->usb_fd, &udd);
	if (retval < 0)
		goto free_and_return;

	for (iConf = 0; iConf < udd.bNumConfigurations; iConf++) {
		ucd = &udd.configurations[iConf];
		for (iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++) {
			uid = &ucd->interfaces[iInterface];
			if(uid->bInterfaceClass    == USB_CLASS_MASS_STORAGE && /*
				   (uid->bInterfaceSubClass == MASS_STORAGE_SCSI_COMMANDS
					|| uid->bInterfaceSubClass == MASS_STORAGE_RBC_COMMANDS
					|| uid->bInterfaceSubClass == MASS_STORAGE_ATA_COMMANDS
					|| uid->bInterfaceSubClass == MASS_STORAGE_QIC_COMMANDS
					|| uid->bInterfaceSubClass == MASS_STORAGE_UFI_COMMANDS
					|| uid->bInterfaceSubClass == MASS_STORAGE_SFF8070_COMMANDS) &&*/
				   uid->bInterfaceProtocol == MASS_STORAGE_BULK_ONLY)
			{
				
				if (uid->bNumEndpoints < 2)
					continue;

				dev->ep_in = dev->ep_out = 0;
				for (iEp = 0; iEp < uid->bNumEndpoints; iEp++) {
					ued = &uid->endpoints[iEp];
					if (ued->bmAttributes != USB_ENDPOINT_BULK)
						continue;

					if (ued->bEndpointAddress & USB_ENDPOINT_IN) {
						dev->ep_in = ued->bEndpointAddress;
					}
					else {
						dev->ep_out = ued->bEndpointAddress;
						if(ued->wMaxPacketSize > 64 && (dev->usb_fd>=0x20 || dev->usb_fd<-1)) 
							usb2_mode=true;
						else 
							usb2_mode=false;
					}
				}

				if (dev->ep_in != 0 && dev->ep_out != 0) {
					dev->configuration = ucd->bConfigurationValue;
					dev->interface = uid->bInterfaceNumber;
					dev->altInterface = uid->bAlternateSetting;
					goto found;
				}
			}
		}
	}

	USB_OGC_FreeDescriptors(&udd);
	retval = USBSTORAGE_ENOINTERFACE;
	goto free_and_return;

found:
	dev->bInterfaceSubClass = uid->bInterfaceSubClass;

	USB_OGC_FreeDescriptors(&udd);

	retval = USBSTORAGE_EINIT;
	// some devices return an error, ignore it
	USB_OGC_GetConfiguration(dev->usb_fd, &conf);

	if (conf != dev->configuration) USB_OGC_SetConfiguration(dev->usb_fd, dev->configuration);
	if (dev->altInterface !=0) USB_OGC_SetAlternativeInterface(dev->usb_fd, dev->interface, dev->altInterface);

	if(!usb2_mode)
		retval = USBStorageOGC_Reset(dev);

	dev->suspended = 0;

	LWP_MutexLock(dev->lock);
	retval = __USB_CtrlMsgTimeout(dev, (USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_GET_MAX_LUN, 0, dev->interface, 1, max_lun);
	LWP_MutexUnlock(dev->lock);
	
	if (retval < 0)
		dev->max_lun = 1;
	else
		dev->max_lun = *max_lun + 1;

	if (retval == USBSTORAGE_ETIMEDOUT)
		goto free_and_return;

	retval = USBSTORAGE_OK;
	dev->sector_size = (u32 *) calloc(dev->max_lun, sizeof(u32));
	if(!dev->sector_size) {
		retval = IPC_ENOMEM;
		goto free_and_return;
	}

	/* taken from linux usbstorage module (drivers/usb/storage/transport.c)
	 *
	 * 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).
	 *
	 * 8/9/10: If anyone wants to actually use a Zip100, they can add this back.
	 * But for now, it seems to be breaking things more than it is helping.
	 */
	//USB_ClearHalt(dev->usb_fd, dev->ep_in);
	//USB_ClearHalt(dev->usb_fd, dev->ep_out);

	if(!dev->buffer)
		dev->buffer = __lwp_heap_allocate(&__heap, MAX_TRANSFER_SIZE_V5);

	if(!dev->buffer) {
		retval = IPC_ENOMEM;
	} else {
		USB_OGC_DeviceRemovalNotifyAsync(dev->usb_fd,__usb_deviceremoved_cb,dev);
		retval = USBSTORAGE_OK;
	}

free_and_return:
	if (max_lun)
		__lwp_heap_free(&__heap, max_lun);

	if (retval < 0) {
		USBStorageOGC_Close(dev);
		return retval;
	}

	return 0;
}
Exemple #5
0
static s32 __usbstorage_reset(struct ehci_hcd * ehci, usbstorage_handle *dev, int hard_reset) {
	s32 retval;
	u32 old_usb_timeout = usb_timeout;
	usb_timeout = 1000 * 1000;
	//int retry = hard_reset;
	int retry = 0; //first try soft reset
retry:
	if (retry >= 1) {
		u8 conf;
		debug_printf("reset device..\n");
		retval = ehci_reset_device(ehci, dev->usb_fd);
		ehci_msleep(10);
		if (retval == -ENODEV) return retval;

		if (retval < 0 && retval != -7004)
			goto end;
		// reset configuration
		if (USB_GetConfiguration(ehci, dev->usb_fd, &conf) < 0)
			goto end;
		if (/*conf != dev->configuration &&*/ USB_SetConfiguration(ehci, dev->usb_fd, dev->configuration) < 0)
			goto end;
		if (dev->altInterface != 0 && USB_SetAlternativeInterface(ehci, dev->usb_fd, dev->interface, dev->altInterface) < 0)
			goto end;
		
		
		
		// find the device with the same ehci ptr
		ehci_device_data * _device_data = find_ehci_data(ehci);
		
		if (_device_data->__lun != 16) {
			if (USBStorage_MountLUN(ehci, &_device_data->__usbfd, _device_data->__lun) < 0)
				goto end;
		}
	}
	debug_printf("usbstorage reset..\n");
	retval = __USB_CtrlMsgTimeout(ehci, dev, (USB_CTRLTYPE_DIR_HOST2DEVICE | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_RESET, 0, dev->interface, 0, NULL);

#ifdef MEM_PRINT
	s_printf("usbstorage reset: Reset ret %i\n", retval);

#endif

	/* FIXME?: some devices return -7004 here which definitely violates the usb ms protocol but they still seem to be working... */
	if (retval < 0 && retval != -7004)
		goto end;


	/* gives device enough time to process the reset */
	ehci_msleep(10);


	debug_printf("clear halt on bulk ep..\n");
	retval = USB_ClearHalt(ehci, dev->usb_fd, dev->ep_in);

#ifdef MEM_PRINT
	s_printf("usbstorage reset: clearhalt in ret %i\n", retval);

#endif
	if (retval < 0)
		goto end;
	ehci_msleep(10);
	retval = USB_ClearHalt(ehci, dev->usb_fd, dev->ep_out);

#ifdef MEM_PRINT
	s_printf("usbstorage reset: clearhalt in ret %i\n", retval);

#endif
	if (retval < 0)
		goto end;
	ehci_msleep(50);
	usb_timeout = old_usb_timeout;
	return retval;

end:
	if (retval == -ENODEV) return retval;
#ifdef HOMEBREW
	if (disable_hardreset) return retval;
	if (retry < 1) { //only 1 hard reset
		ehci_msleep(100);
		debug_printf("retry with hard reset..\n");
		retry++;
		goto retry;
	}
#else
	if (retry < 5) {
		ehci_msleep(100);
		debug_printf("retry with hard reset..\n");

		retry++;
		goto retry;
	}
#endif
	usb_timeout = old_usb_timeout;
	return retval;
}
Exemple #6
0
s32 USBStorage_Try_Device(ehci_device_data * device_data) {
	struct ehci_hcd * ehci; struct ehci_device *fd;
	int maxLun, j, retval;
	int test_max_lun = 1;
	
	ehci = device_data->__ehci;
	fd = device_data->__dev;

	try_status = -120;
	if (USBStorage_Open(device_data) < 0)
		return -EINVAL;

	/*
	   maxLun = USBStorage_GetMaxLUN(&__usbfd);
	   if(maxLun == USBSTORAGE_ETIMEDOUT)
			{
			__mounted = 0;
			USBStorage_Close(&__usbfd);
			return -EINVAL;
			}
	 */

	maxLun = 1;
	device_data->__usbfd.max_lun = 1;

	j = 0;
	//for(j = 0; j < maxLun; j++)
	while (1) {

#ifdef MEM_PRINT
		s_printf("USBStorage_MountLUN %i#\n", j);
#endif
		retval = USBStorage_MountLUN(ehci, &device_data->__usbfd, j);
#ifdef MEM_PRINT
		s_printf("USBStorage_MountLUN: ret %i\n", retval);
#endif


		if (retval == USBSTORAGE_ETIMEDOUT /*&& test_max_lun==0*/) {
			//USBStorage_Reset(&__usbfd);
			try_status = -121;
			device_data->__mounted = 0;
			USBStorage_Close(&device_data->__usbfd);
			return -EINVAL;
			//  break;
		}

		if (retval < 0) {
			if (test_max_lun) {
				device_data->__usbfd.max_lun = 0;
				retval = __USB_CtrlMsgTimeout(ehci, &device_data->__usbfd,
						(USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE),
						USBSTORAGE_GET_MAX_LUN, 0, device_data->__usbfd.interface, 1, &device_data->__usbfd.max_lun);
				if (retval < 0)
					device_data->__usbfd.max_lun = 1;
				else device_data->__usbfd.max_lun++;
				maxLun =device_data-> __usbfd.max_lun;

#ifdef MEM_PRINT
				s_printf("USBSTORAGE_GET_MAX_LUN ret %i maxlun %i\n", retval, maxLun);
#endif
				test_max_lun = 0;
			} else j++;

			if (j >= maxLun) break;
			continue;
		}

		device_data->__vid = fd->desc.idVendor;
		device_data->__pid = fd->desc.idProduct;
		device_data->__mounted = 1;
		device_data->__lun = j;
		usb_timeout = 1000 * 1000;
		try_status = 0;
		return 0;
	}
	try_status = -122;
	device_data->__mounted = 0;
	USBStorage_Close(&device_data->__usbfd);

#ifdef MEM_PRINT
	s_printf("USBStorage_MountLUN fail!!!\n");
#endif

	return -EINVAL;
}
Exemple #7
0
s32 USBStorage_Open(usbstorage_handle *dev, struct ehci_device *fd)
{
	s32 retval = -1;
	u8 conf,*max_lun = NULL;
	u32 iConf, iInterface, iEp;
	usb_devdesc udd;
	usb_configurationdesc *ucd;
	usb_interfacedesc *uid;
	usb_endpointdesc *ued;

	max_lun = USB_Alloc(1);
	if(max_lun==NULL) return -ENOMEM;

	memset(dev, 0, sizeof(*dev));

	dev->tag = TAG_START;
        dev->usb_fd = fd;

	retval = USB_GetDescriptors(dev->usb_fd, &udd);
	if(retval < 0)
		goto free_and_return;

	for(iConf = 0; iConf < udd.bNumConfigurations; iConf++)
	{
		ucd = &udd.configurations[iConf];		
		for(iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++)
		{
			uid = &ucd->interfaces[iInterface];
			if(uid->bInterfaceClass    == USB_CLASS_MASS_STORAGE &&
			   uid->bInterfaceSubClass == MASS_STORAGE_SCSI_COMMANDS &&
			   uid->bInterfaceProtocol == MASS_STORAGE_BULK_ONLY)
			{
				if(uid->bNumEndpoints < 2)
					continue;

				dev->ep_in = dev->ep_out = 0;
				for(iEp = 0; iEp < uid->bNumEndpoints; iEp++)
				{
					ued = &uid->endpoints[iEp];
					if(ued->bmAttributes != USB_ENDPOINT_BULK)
						continue;

					if(ued->bEndpointAddress & USB_ENDPOINT_IN)
						dev->ep_in = ued->bEndpointAddress;
					else
						dev->ep_out = ued->bEndpointAddress;
				}
				if(dev->ep_in != 0 && dev->ep_out != 0)
				{
					dev->configuration = ucd->bConfigurationValue;
					dev->interface = uid->bInterfaceNumber;
					dev->altInterface = uid->bAlternateSetting;
					goto found;
				}
			}
		}
	}

	USB_FreeDescriptors(&udd);
	retval = USBSTORAGE_ENOINTERFACE;
	goto free_and_return;

found:
	USB_FreeDescriptors(&udd);

	retval = USBSTORAGE_EINIT;
	if(USB_GetConfiguration(dev->usb_fd, &conf) < 0)
		goto free_and_return;
	if(conf != dev->configuration && USB_SetConfiguration(dev->usb_fd, dev->configuration) < 0)
		goto free_and_return;
	if(dev->altInterface != 0 && USB_SetAlternativeInterface(dev->usb_fd, dev->interface, dev->altInterface) < 0)
		goto free_and_return;
	dev->suspended = 0;

	retval = USBStorage_Reset(dev);
	if(retval < 0)
		goto free_and_return;

	retval = __USB_CtrlMsgTimeout(dev, (USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_GET_MAX_LUN, 0, dev->interface, 1, max_lun);
	if(retval < 0)
		dev->max_lun = 1;
	else
		dev->max_lun = *max_lun;

	
	if(retval == USBSTORAGE_ETIMEDOUT)
		goto free_and_return;

	retval = USBSTORAGE_OK;

	if(dev->max_lun == 0)
		dev->max_lun++;

	/* taken from linux usbstorage module (drivers/usb/storage/transport.c) */
	/*
	 * 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).
	 */
	USB_ClearHalt(dev->usb_fd, dev->ep_in);
	USB_ClearHalt(dev->usb_fd, dev->ep_out);

	dev->buffer = USB_Alloc(MAX_TRANSFER_SIZE);
	
	if(dev->buffer == NULL) retval = -ENOMEM;
	else retval = USBSTORAGE_OK;

free_and_return:
	if(max_lun!=NULL) USB_Free(max_lun);
	if(retval < 0)
	{
		if(dev->buffer != NULL)
			USB_Free(dev->buffer);
		memset(dev, 0, sizeof(*dev));
		return retval;
	}
	return 0;
}