예제 #1
0
static int
ioctl_usbpd(struct inode *inode, struct file *file, unsigned int cmd,
	  unsigned long arg)
{
	struct USBPDCommand usbpd_cmd;
	struct usbpd_usb_data *usbpd = file->private_data;
	void *data;
	unsigned char *buffer;
	int result = 0, requesttype;

        /* Sanity check to make sure usbpd is connected, powered, etc */
	if ( usbpd == NULL )
		return -EINVAL;

	down(&usbpd->lock);
	if ( usbpd->present == 0 ||
	     usbpd->usbpd_dev == NULL ) {
		up(&usbpd->lock);
		return -EINVAL;
	}

	switch (cmd) {
	case USBPD_RECV_COMMAND:
		dbg("USBPD_RECV_COMMAND");
		data = (void *) arg;
		if (data == NULL)
			break;
		if (copy_from_user(&usbpd_cmd, data, sizeof(struct USBPDCommand))) {
			up(&usbpd->lock);
			return -EFAULT;
		}
		if (usbpd_cmd.length > PAGE_SIZE) {
			up(&usbpd->lock);
			return -EINVAL;
		}
		buffer = (unsigned char *) __get_free_page(GFP_KERNEL);
		if (buffer == NULL) {
			up(&usbpd->lock);
			return -ENOMEM;
		}
		if (copy_from_user(buffer, usbpd_cmd.buffer, usbpd_cmd.length)) {
			up(&usbpd->lock);
			return -EFAULT;
		}

		requesttype = usbpd_cmd.requesttype | USB_DIR_IN |
		    USB_TYPE_VENDOR | USB_RECIP_DEVICE;
		dbg
		    ("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x",
		     requesttype, usbpd_cmd.request, usbpd_cmd.value,
		     usbpd_cmd.index, usbpd_cmd.length);
		/* Send usbpd control message */
		result = usb_control_msg(usbpd->usbpd_dev,
					 usb_rcvctrlpipe(usbpd-> usbpd_dev, 0),
					 usbpd_cmd.request,
					 requesttype,
					 usbpd_cmd.value,
					 usbpd_cmd.index, buffer,
					 usbpd_cmd.length,
					 usbpd_cmd.timeout);
		if (result < 0) {
			err("Error executing ioctrl. code = %d",
			     le32_to_cpu(result));
		} else {
			dbg("Executed ioctl. Result = %d (data=%04x)",
			     le32_to_cpu(result),
			     le32_to_cpu(*((long *) buffer)));
			if (copy_to_user(usbpd_cmd.buffer, buffer,
					 usbpd_cmd.length)) {
				up(&usbpd->lock);
				return -EFAULT;
			}
		}

		/* usbpd_cmd.buffer contains a raw stream of single byte
		   data which has been returned from usbpd.  Data is
		   interpreted at application level.  For data that
		   will be cast to data types longer than 1 byte, data
		   will be little_endian and will potentially need to
		   be swapped at the app level */

		free_page((unsigned long) buffer);
		break;

	case USBPD_SEND_COMMAND:
		dbg("USBPD_SEND_COMMAND");
		data = (void *) arg;
		if (data == NULL)
			break;
		if (copy_from_user(&usbpd_cmd, data, sizeof(struct USBPDCommand))) {
			up(&usbpd->lock);
			return -EFAULT;
		}
		if (usbpd_cmd.length > PAGE_SIZE) {
			up(&usbpd->lock);
			return -EINVAL;
		}
		buffer = (unsigned char *) __get_free_page(GFP_KERNEL);
		if (buffer == NULL) {
			up(&usbpd->lock);
			return -ENOMEM;
		}
		if (copy_from_user(buffer, usbpd_cmd.buffer, usbpd_cmd.length)) {
			up(&usbpd->lock);
			return -EFAULT;
		}

		requesttype = usbpd_cmd.requesttype | USB_DIR_OUT |
		    USB_TYPE_VENDOR | USB_RECIP_DEVICE;
		dbg("sending command: reqtype=%0x req=%0x value=%0x index=%0x len=%0x",
		     requesttype, usbpd_cmd.request, usbpd_cmd.value,
		     usbpd_cmd.index, usbpd_cmd.length);
		/* Send usbpd control message */
		result = usb_control_msg(usbpd->usbpd_dev,
					 usb_sndctrlpipe(usbpd-> usbpd_dev, 0),
					 usbpd_cmd.request,
					 requesttype,
					 usbpd_cmd.value,
					 usbpd_cmd.index, buffer,
					 usbpd_cmd.length,
					 usbpd_cmd.timeout);
		if (result < 0) {
			err("Error executing ioctrl. code = %d",
			     le32_to_cpu(result));
		} else {
			dbg("Executed ioctl. Result = %d",
			       le32_to_cpu(result));
		}

		free_page((unsigned long) buffer);
		break;

	case USBPD_DEVICE_INFO:
		data = (void *) arg;
		if (data == NULL)
			break;
		usb_get_configuration(usbpd->usbpd_dev);
		dbg("deviceID = %x ProductID = %x", 
		    usbpd->usbpd_dev->descriptor.idVendor, usbpd->usbpd_dev->descriptor.idProduct);
		copy_to_user(data, &usbpd->usbpd_dev->descriptor, sizeof(struct usb_device_descriptor));
		copy_to_user(data+sizeof(struct usb_device_descriptor), &usbpd->usbpd_dev->devnum, sizeof(int));
		copy_to_user(data+sizeof(struct usb_device_descriptor)+sizeof(int), &usbpd->pdtype, sizeof(int));
		break;

	default:
		up(&usbpd->lock);
		return -ENOIOCTLCMD;
		break;
	}

	up(&usbpd->lock);
	return (result < 0) ? result : 0;
}
예제 #2
0
파일: hub.c 프로젝트: niubl/camera_project
/*
 * WARNING - If a driver calls usb_reset_device, you should simulate a
 * disconnect() and probe() for other interfaces you doesn't claim. This
 * is left up to the driver writer right now. This insures other drivers
 * have a chance to re-setup their interface.
 *
 * Take a look at proc_resetdevice in devio.c for some sample code to
 * do this.
 */
int usb_reset_device(struct usb_device *dev)
{
	struct usb_device *parent = dev->parent;
	struct usb_device_descriptor descriptor;
	int i, ret, port = -1;

    DBG_HOST_HUB("### >>> Enter hub.c file --> usb_reset_device function \n");
	if (!parent) {
		err("attempting to reset root hub!");
		return -EINVAL;
	}

	for (i = 0; i < parent->maxchild; i++)
		if (parent->children[i] == dev) {
			port = i;
			break;
		}

	if (port < 0)
		return -ENOENT;

	down(&usb_address0_sem);

	/* Send a reset to the device */
	if (usb_hub_port_reset(parent, port, dev, HUB_SHORT_RESET_TIME)) {
		usb_hub_port_disable(parent, port);
		up(&usb_address0_sem);
		return(-ENODEV);
	}

	/* Reprogram the Address */
	ret = usb_set_address(dev);
	if (ret < 0) {
		err("USB device not accepting new address (error=%d)", ret);
		usb_hub_port_disable(parent, port);
		up(&usb_address0_sem);
		return ret;
	}

	/* Let the SET_ADDRESS settle */
	wait_ms(10);

	up(&usb_address0_sem);

	/*
	 * Now we fetch the configuration descriptors for the device and
	 * see if anything has changed. If it has, we dump the current
	 * parsed descriptors and reparse from scratch. Then we leave
	 * the device alone for the caller to finish setting up.
	 *
	 * If nothing changed, we reprogram the configuration and then
	 * the alternate settings.
	 */
	ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &descriptor,
			sizeof(descriptor));
	if (ret < 0)
		return ret;

	le16_to_cpus(&descriptor.bcdUSB);
	le16_to_cpus(&descriptor.idVendor);
	le16_to_cpus(&descriptor.idProduct);
	le16_to_cpus(&descriptor.bcdDevice);

	if (memcmp(&dev->descriptor, &descriptor, sizeof(descriptor))) {
		usb_destroy_configuration(dev);

		ret = usb_get_device_descriptor(dev);
		if (ret < sizeof(dev->descriptor)) {
			if (ret < 0)
				err("unable to get device descriptor (error=%d)", ret);
			else
				err("USB device descriptor short read (expected %Zi, got %i)", sizeof(dev->descriptor), ret);
        
			clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
			dev->devnum = -1;
			return -EIO;
		}

		ret = usb_get_configuration(dev);
		if (ret < 0) {
			err("unable to get configuration (error=%d)", ret);
			usb_destroy_configuration(dev);
			clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
			dev->devnum = -1;
			return 1;
		}

		dev->actconfig = dev->config;
		usb_set_maxpacket(dev);

		return 1;
	}

	ret = usb_set_configuration(dev, dev->actconfig->bConfigurationValue);
	if (ret < 0) {
		err("failed to set active configuration (error=%d)", ret);
		return ret;
	}

	for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
		struct usb_interface *intf = &dev->actconfig->interface[i];
		struct usb_interface_descriptor *as = &intf->altsetting[intf->act_altsetting];

		ret = usb_set_interface(dev, as->bInterfaceNumber, as->bAlternateSetting);
		if (ret < 0) {
			err("failed to set active alternate setting for interface %d (error=%d)", i, ret);
			return ret;
		}
	}

	return 0;
}
예제 #3
0
//! This function reads the SETUP request sent to the default control endpoint
//! and calls the appropriate function. When exiting of the usb_read_request
//! function, the device is ready to manage the next request.
//!
//! If the received request is not supported or a non-standard USB request, the function
//! will call the custom decoding function in usb_specific_request module.
//!
//! @note List of supported requests:
//! GET_DESCRIPTOR
//! GET_CONFIGURATION
//! SET_ADDRESS
//! SET_CONFIGURATION
//! CLEAR_FEATURE
//! SET_FEATURE
//! GET_STATUS
//!
void usb_process_request(void)
{
  U8 bRequest;

  Usb_reset_endpoint_fifo_access(EP_CONTROL);
  bmRequestType = Usb_read_endpoint_data(EP_CONTROL, 8);
  bRequest      = Usb_read_endpoint_data(EP_CONTROL, 8);

  switch (bRequest)
  {
  case GET_DESCRIPTOR:
    if (bmRequestType == 0x80) usb_get_descriptor();
    else goto unsupported_request;
    break;

  case GET_CONFIGURATION:
    if (bmRequestType == 0x80) usb_get_configuration();
    else goto unsupported_request;
    break;

  case SET_ADDRESS:
    if (bmRequestType == 0x00) usb_set_address();
    else goto unsupported_request;
    break;

  case SET_CONFIGURATION:
    if (bmRequestType == 0x00) usb_set_configuration();
    else goto unsupported_request;
    break;

  case CLEAR_FEATURE:
    if (bmRequestType <= 0x02) usb_clear_feature();
    else goto unsupported_request;
    break;

  case SET_FEATURE:
    if (bmRequestType <= 0x02) usb_set_feature();
    else goto unsupported_request;
    break;

  case GET_STATUS:
    if (0x7F < bmRequestType && bmRequestType <= 0x82) usb_get_status();
    else goto unsupported_request;
    break;

  case GET_INTERFACE:
    if (bmRequestType == 0x81)
    {
      if(!usb_get_interface())
      {
        Usb_enable_stall_handshake(EP_CONTROL);
        Usb_ack_setup_received_free();
      }
    }
    else goto unsupported_request;
    break;

  case SET_INTERFACE:
    if (bmRequestType == 0x01) usb_set_interface();
    else goto unsupported_request;
    break;

  case SET_DESCRIPTOR:
  case SYNCH_FRAME:
  default:  //!< unsupported request => call to user read request
unsupported_request:
    if (!usb_user_read_request(bmRequestType, bRequest))
    {
      Usb_enable_stall_handshake(EP_CONTROL);
      Usb_ack_setup_received_free();
    }
    break;
  }
}
예제 #4
0
//! usb_process_request.
//!
//! @brief This function reads the SETUP request sent to the default control endpoint
//! and calls the appropriate function. When exiting of the usb_read_request
//! function, the device is ready to manage the next request.
//!
//! @param none
//!
//! @return none
//! @note list of supported requests:
//! GET_DESCRIPTOR
//! GET_CONFIGURATION
//! SET_ADDRESS
//! SET_CONFIGURATION
//! CLEAR_FEATURE
//! SET_FEATURE
//! GET_STATUS
//!
void usb_process_request(void)
{
   U8  bmRequest;

   bmRequestType = Usb_read_byte();
   bmRequest     = Usb_read_byte();

   switch (bmRequest)
   {
    case GET_DESCRIPTOR:
         if (0x80 == bmRequestType) { usb_get_descriptor(); }
         else                       { usb_user_read_request(bmRequestType, bmRequest); }
         break;

    case GET_CONFIGURATION:
         if (0x80 == bmRequestType) { usb_get_configuration(); }
         else                       { usb_user_read_request(bmRequestType, bmRequest); }
         break;

    case SET_ADDRESS:
         if (0x00 == bmRequestType) { usb_set_address(); }
         else                       { usb_user_read_request(bmRequestType, bmRequest); }
         break;

    case SET_CONFIGURATION:
         if (0x00 == bmRequestType) { usb_set_configuration(); }
         else                       { usb_user_read_request(bmRequestType, bmRequest); }
         break;

    case CLEAR_FEATURE:
         if (0x02 >= bmRequestType) { usb_clear_feature(); }
         else                       { usb_user_read_request(bmRequestType, bmRequest); }
         break;

    case SET_FEATURE:
         if (0x02 >= bmRequestType) { usb_set_feature(); }
         else                       { usb_user_read_request(bmRequestType, bmRequest); }
         break;

    case GET_STATUS:
         if ((0x7F < bmRequestType) & (0x82 >= bmRequestType))
                                    { usb_get_status(); }
         else                       { usb_user_read_request(bmRequestType, bmRequest); }
         break;

    case GET_INTERFACE:
          if (bmRequestType == 0x81) { usb_get_interface(); }
          else { usb_user_read_request(bmRequestType, bmRequest); }
          break;


    case SET_INTERFACE:
      if (bmRequestType == 0x01) {usb_set_interface();}
      break;

    case SET_DESCRIPTOR:
    case SYNCH_FRAME:
    default: //!< un-supported request => call to user read request
         if(usb_user_read_request(bmRequestType, bmRequest) == FALSE)
         {
            Usb_enable_stall_handshake();
            Usb_ack_receive_setup();
            return;
         }
         break;
  }
}
//! usb_process_request.
//!
//! @brief This function reads the SETUP request sent to the default control endpoint
//! and calls the appropriate function. When exiting of the usb_read_request
//! function, the device is ready to manage the next request.
//!
//! @note list of supported requests:
//! GET_DESCRIPTOR
//! GET_CONFIGURATION
//! SET_ADDRESS
//! SET_CONFIGURATION
//! CLEAR_FEATURE
//! SET_FEATURE
//! GET_STATUS
//!
void usb_process_request(void)
{
   U8  bmRequest;

   bmRequestType = Usb_read_byte();
   bmRequest     = Usb_read_byte();

   switch (bmRequest)
   {
    case GET_DESCRIPTOR:
         if (0x80 == bmRequestType) { usb_get_descriptor(); }
         else goto user_read;
         break;

    case GET_CONFIGURATION:
         if (0x80 == bmRequestType) { usb_get_configuration(); }
         else goto user_read;
         break;

    case SET_ADDRESS:
         if (0x00 == bmRequestType) { usb_set_address(); }
         else goto user_read;
         break;

    case SET_CONFIGURATION:
         if (0x00 == bmRequestType) { usb_set_configuration(); }
         else goto user_read;
         break;

    case CLEAR_FEATURE:
         if (0x02 >= bmRequestType) { usb_clear_feature(); }
         else goto user_read;
         break;

    case SET_FEATURE:
         if (0x02 >= bmRequestType) { usb_set_feature(); }
         else goto user_read;
         break;

    case GET_STATUS:
         if ((0x7F < bmRequestType) & (0x82 >= bmRequestType))
                                    { usb_get_status(); }
         else goto user_read;
         break;

    case GET_INTERFACE:
          if (bmRequestType == 0x81) { usb_get_interface(); }
		  else goto user_read;
          break;


    case SET_INTERFACE:
      if (bmRequestType == 0x01) {usb_set_interface();}
      break;

    case SET_DESCRIPTOR:
    case SYNCH_FRAME:
    default: //!< un-supported request => call to user read request
	user_read:
         usb_user_read_request(bmRequestType, bmRequest);
         break;
  }
	
	Usb_select_endpoint(EP_CONTROL);

	// If the receive setup flag hasn't been cleared
	// by this point then we can assume that we didn't
	// support this request and should stall.
	if(Is_usb_receive_setup())
		Usb_enable_stall_handshake();
	
	// Clear some flags.
	Usb_ack_receive_setup();
	Usb_ack_receive_out();
	Usb_ack_in_ready();
}
/*
 * Read the SETUP request sent to the default control endpoint
 * and call the appropriate function. When exiting this
 * function, the device is ready to manage the next request.
 *
 * Supported requests:
 * GET_DESCRIPTOR
 * GET_CONFIGURATION
 * SET_ADDRESS
 * SET_CONFIGURATION
 * CLEAR_FEATURE
 * SET_FEATURE
 * GET_STATUS
 */
void
OSUsbDeviceImpl::standardProcessRequest(void)
{
  unsigned char bmRequest;

  bmRequestType = OSUsbDeviceImpl::readByte();
  bmRequest = OSUsbDeviceImpl::readByte();

#if defined(DEBUG) && defined(OS_DEBUG_OSUSBDEVICE_REQUEST)
  OSDeviceDebug::putString("type/req=");
  OSDeviceDebug::putHex(bmRequestType);
  OSDeviceDebug::putString("/");
  OSDeviceDebug::putHex(bmRequest);
  OSDeviceDebug::putString(" ");
  //OSDeviceDebug::putNewLine();
#endif

  switch (bmRequest)
    {
  case GET_DESCRIPTOR:
    if (0x80 == bmRequestType)
      {
        OSUsbDeviceImpl::usb_get_descriptor();
        return;
      }
    break;

  case GET_CONFIGURATION:
    if (0x80 == bmRequestType)
      {
        usb_get_configuration();
        return;
      }
    break;

  case SET_ADDRESS:
    if (0x00 == bmRequestType)
      {
        usb_set_address();
        return;
      }
    break;

  case SET_CONFIGURATION:
    if (0x00 == bmRequestType)
      {
        usb_set_configuration();
        return;
      }
    break;

  case CLEAR_FEATURE:
    if (0x02 >= bmRequestType)
      {
        usb_clear_feature();
        return;
      }
    break;

  case SET_FEATURE:
    if (0x02 >= bmRequestType)
      {
        usb_set_feature();
        return;
      }
    break;

  case GET_STATUS:
    if ((0x7F < bmRequestType) & (0x82 >= bmRequestType))
      {
        usb_get_status();
        return;
      }
    break;

  case GET_INTERFACE:
    if (bmRequestType == 0x81)
      {
        usb_get_interface();
        return;
      }
    break;

  case SET_INTERFACE:
    if (bmRequestType == 0x01)
      {
        usb_set_interface();
        return;
      }
    break;

  case SET_DESCRIPTOR:
  case SYNCH_FRAME:
  default:
    break;
    }

  // for un-supported requests call the specific read request
  if (OSUsbDeviceImpl::specificProcessReadRequest(bmRequestType, bmRequest))
    return;

  // if nothing worked, reply with stall
  OSUsbDeviceImpl::Usb_enable_stall_handshake();
  OSUsbDeviceImpl::Usb_ack_receive_setup();
}
//! @brief This function reads the SETUP request sent to the default control endpoint
//! and calls the appropriate function. When exiting of the usb_read_request
//! function, the device is ready to manage the next request.
//!
void usb_process_request(void)
{
   U8 bmRequestType;
   U8 bmRequest;

   Usb_ack_control_out();
   bmRequestType = Usb_read_byte();
   bmRequest     = Usb_read_byte();

   switch (bmRequest)
   {
      case SETUP_GET_DESCRIPTOR:
      if (USB_SETUP_GET_STAND_DEVICE == bmRequestType)
      {     
         if( usb_get_descriptor() )
            return;
      }
      break;

      case SETUP_GET_CONFIGURATION:
      if (USB_SETUP_GET_STAND_DEVICE == bmRequestType)
      {
         usb_get_configuration();
         return;
      }
      break;

      case SETUP_SET_ADDRESS:
      if (USB_SETUP_SET_STAND_DEVICE == bmRequestType)
      {
         usb_set_address();
         return;
      }
      break;

      case SETUP_SET_CONFIGURATION:
      if (USB_SETUP_SET_STAND_DEVICE == bmRequestType)
      { 
         if( usb_set_configuration() )
            return;
      }
      break;

      case SETUP_CLEAR_FEATURE:
      if (usb_clear_feature(bmRequestType))
         return;
      break;

      case SETUP_SET_FEATURE:
      if (usb_set_feature(bmRequestType))
         return;
      break;

      case SETUP_GET_STATUS:
      if (usb_get_status(bmRequestType))
         return;
      break;

      case SETUP_GET_INTERFACE:
      if (USB_SETUP_GET_STAND_INTERFACE == bmRequestType)
      {
         if( usb_get_interface() )
            return;
      }
      break;

      case SETUP_SET_INTERFACE:
      if (bmRequestType == USB_SETUP_SET_STAND_INTERFACE)
      {
         if( usb_set_interface() )
            return;
      }
      break;

      default:
      break;
   }

   // un-supported like standard request => call to user read request
   if( !usb_user_read_request(bmRequestType, bmRequest) )
   {
      // Request unknow in the specific request list from interface
      // keep that order (set StallRq/clear RxSetup) or a
      // OUT request following the SETUP may be acknowledged
      Usb_enable_stall_handshake();
      Usb_ack_receive_setup();
      endpoint_status[(EP_CONTROL & MSK_EP_DIR)] = 0x01;
   }
}