コード例 #1
0
ファイル: hub.c プロジェクト: Polo35/PSFreedom
static void
hub_connect_port (struct psfreedom_device *dev, unsigned int port)
{
  if (port == 0 || port > 6)
    return;

  switch_to_port (dev, 0);

  /* Here, we must enable the port directly, otherwise we might loose time
     with the host asking for the status a few more times, and waiting for it to
     be enabled, etc.. and we might miss the 5seconds window in which we need
     to connect the JIG */
  dev->hub_ports[port-1].status |= PORT_STAT_CONNECTION;
  dev->hub_ports[port-1].status |= PORT_STAT_ENABLE;

  /* If the speed flag set is not the same as what the device suports, it will
     not work */
  if (psfreedom_is_high_speed ())
    dev->hub_ports[port-1].status |= PORT_STAT_HIGH_SPEED;
  else if (psfreedom_is_low_speed ())
    dev->hub_ports[port-1].status |= PORT_STAT_HIGH_SPEED;

  dev->hub_ports[port-1].change |= PORT_STAT_C_CONNECTION;
  hub_port_changed (dev);
}
コード例 #2
0
ファイル: hub.c プロジェクト: Polo35/PSFreedom
static void
hub_disconnect_port (struct psfreedom_device *dev, unsigned int port)
{
  if (port == 0 || port > 6)
    return;

  switch_to_port (dev, 0);
  dev->hub_ports[port-1].status &= ~PORT_STAT_CONNECTION;
  dev->hub_ports[port-1].status &= ~PORT_STAT_ENABLE;
  dev->hub_ports[port-1].status &= ~PORT_STAT_HIGH_SPEED;
  dev->hub_ports[port-1].status &= ~PORT_STAT_LOW_SPEED;
  dev->hub_ports[port-1].change |= PORT_STAT_C_CONNECTION;
  hub_port_changed (dev);
}
コード例 #3
0
ファイル: hub.c プロジェクト: granberro/PSjbiPAQ
static void hub_disconnect_port (unsigned int port)
{
	if (port == 0 || port > 6) {
		return;
	}

	switch_to_port (0);
	
	// After jig send response ep2 needs behave as hub 
	if (machine_state==DEVICE3_WAIT_DISCONNECT) {
		ep2_reset();
	}

	port_status[port-1] &= ~PORT_STAT_CONNECTION;
	port_status[port-1] &= ~PORT_STAT_ENABLE;
	port_change[port-1] |= PORT_STAT_C_CONNECTION;
	hub_port_changed ();
}
コード例 #4
0
ファイル: hub.c プロジェクト: granberro/PSjbiPAQ
static void hub_connect_port (unsigned int port)
{
	if (port == 0 || port > 6) {
		return;
	}
	
	expected_port_reset = port;
	
	//PRINTKD( "[%lu]Hub: Connect port %d\n", (jiffies-start_time)*10, port );
	switch_to_port (0);

	/* Here, we must enable the port directly, otherwise we might loose time
	with the host asking for the status a few more times, and waiting for it to
	be enabled, etc.. and we might miss the 5seconds window in which we need
	to connect the JIG */
	port_status[port-1] |= PORT_STAT_CONNECTION;
	port_status[port-1] |= PORT_STAT_ENABLE;
	port_change[port-1] |= PORT_STAT_C_CONNECTION;

	hub_port_changed ();
}
コード例 #5
0
ファイル: hub.c プロジェクト: Polo35/PSFreedom
/*
 * The setup() callback implements all the ep0 functionality that's
 * not handled lower down, in hardware or the hardware driver (like
 * device and endpoint feature flags, and their status).  It's all
 * housekeeping for the gadget function we're implementing.  Most of
 * the work is in config-specific setup.
 */
static int hub_setup(struct usb_gadget *gadget,
    const struct usb_ctrlrequest *ctrl, u16 request,
    u16 w_index, u16 w_value, u16 w_length)
{
  struct psfreedom_device *dev = get_gadget_data(gadget);
  struct usb_request *req = dev->req;
  int value = -EOPNOTSUPP;

  /* usually this stores reply data in the pre-allocated ep0 buffer,
   * but config change events will reconfigure hardware.
   */
  switch (ctrl->bRequest) {
    case USB_REQ_GET_DESCRIPTOR:
      if ((ctrl->bRequestType & USB_DIR_IN) == 0) {
        goto unknown;
      }
      if ((ctrl->bRequestType & USB_TYPE_CLASS) == USB_TYPE_CLASS) {
        /* GET_HUB_DESCRIPTOR Class specific request */
        value = min(w_length, (u16) sizeof(hub_header_desc));
        memcpy(req->buf, &hub_header_desc, value);
        if (value >= 0)
          value = min(w_length, (u16)value);
      } else {
        switch (w_value >> 8) {
          case USB_DT_DEVICE:
            value = min(w_length, (u16) sizeof(hub_device_desc));
            memcpy(req->buf, &hub_device_desc, value);
            break;
          case USB_DT_CONFIG:
            memcpy(req->buf, &hub_config_desc, sizeof(hub_config_desc));
            value = sizeof(hub_config_desc);
            memcpy (req->buf + value, &hub_interface_desc,
                sizeof(hub_interface_desc));
            value += sizeof(hub_interface_desc);
            memcpy (req->buf + value, &hub_endpoint_desc,
                sizeof(hub_endpoint_desc));
            value += sizeof(hub_endpoint_desc);
            if (value >= 0)
              value = min(w_length, (u16)value);
            break;
          case USB_DT_STRING:
            value = 0;
            break;
        }
      }
      break;

    case USB_REQ_SET_CONFIGURATION:
      if (ctrl->bRequestType != 0) {
        goto unknown;
      }
      value = hub_set_config(dev, w_value);
      break;
    case USB_REQ_GET_CONFIGURATION:
      if (ctrl->bRequestType != USB_DIR_IN) {
        goto unknown;
      }
      *(u8 *)req->buf = 0;
      value = min(w_length, (u16)1);
      break;

    case USB_REQ_SET_INTERFACE:
      if (ctrl->bRequestType != USB_RECIP_INTERFACE) {
        goto unknown;
      }
      value = 0;
      break;
    case USB_REQ_GET_INTERFACE:
      if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) {
        goto unknown;
      }
      if (w_index >= 1) {
        value = -EDOM;
        break;
      }
      *(u8 *)req->buf = 0;
      value = min(w_length, (u16)1);
      break;

    case USB_REQ_SET_FEATURE:
      if ((ctrl->bRequestType & USB_TYPE_CLASS) == USB_TYPE_CLASS) {
        switch (ctrl->bRequestType & USB_RECIP_MASK) {
          /* SET_HUB_FEATURE */
          case USB_RECIP_DEVICE:
            switch (w_value) {
              case 0: /* C_HUB_LOCAL_POWER */
              case 1: /* C_HUB_OVER_CURRENT */
                VDBG (dev, "SetHubFeature called\n");
                value = 0;
                break;
              default:
                value = -EINVAL;
                break;
            }
            break;
          case USB_RECIP_OTHER:
          /* SET_PORT_FEATURE */
            if (w_index == 0 || w_index > 6) {
              DBG (dev, "SetPortFeature: invalid port index %d\n", w_index);
              value = -EINVAL;
              break;
            }
            switch (w_value) {
              case 4: /* PORT_RESET */
                DBG (dev, "SetPortFeature PORT_RESET called\n");
                dev->hub_ports[w_index-1].change |= PORT_STAT_C_RESET;
                hub_port_changed (dev);
                value = 0;
                break;
              case 8: /* PORT_POWER */
                DBG (dev, "SetPortFeature PORT_POWER called\n");
                dev->hub_ports[w_index-1].status |= PORT_STAT_POWER;
                if (dev->status == INIT && w_index == 6) {
                  dev->status = HUB_READY;
                  SET_TIMER (150);
                }
                value = 0;
                break;
              case 0: /* PORT_CONNECTION */
              case 1: /* PORT_ENABLE */
              case 2: /* PORT_SUSPEND */
              case 3: /* PORT_OVER_CURRENT */
              case 9: /* PORT_LOW_SPEED */
              case 16: /* C_PORT_CONNECTION */
              case 17: /* C_PORT_ENABLE */
              case 18: /* C_PORT_SUSPEND */
              case 19: /* C_PORT_OVER_CURRENT */
              case 20: /* C_PORT_RESET */
              case 21: /* PORT_TEST */
              case 22: /* PORT_INDICATOR */
                DBG (dev, "SetPortFeature called\n");
                value = 0;
                break;
              default:
                value = -EINVAL;
                break;
            }
            break;
        }
      }
      break;
    case USB_REQ_CLEAR_FEATURE:
      if ((ctrl->bRequestType & USB_TYPE_CLASS) == USB_TYPE_CLASS) {
        switch (ctrl->bRequestType & USB_RECIP_MASK) {
          /* CLEAR_HUB_FEATURE */
          case USB_RECIP_DEVICE:
            switch (w_value) {
              case 0: /* C_HUB_LOCAL_POWER */
              case 1: /* C_HUB_OVER_CURRENT */
                VDBG (dev, "ClearHubFeature called\n");
                value = 0;
                break;
              default:
                value = -EINVAL;
                break;
            }
            break;
          case USB_RECIP_OTHER:
            /* CLEAR_PORT_FEATURE */
            if (w_index == 0 || w_index > 6) {
              DBG (dev, "ClearPortFeature: invalid port index %d\n", w_index);
              value = -EINVAL;
              break;
            }
            switch (w_value) {
              case 0: /* PORT_CONNECTION */
              case 1: /* PORT_ENABLE */
              case 2: /* PORT_SUSPEND */
              case 3: /* PORT_OVER_CURRENT */
              case 4: /* PORT_RESET */
              case 8: /* PORT_POWER */
              case 9: /* PORT_LOW_SPEED */
                value = 0;
                break;
              case 16: /* C_PORT_CONNECTION */
                DBG (dev, "ClearPortFeature C_PORT_CONNECTION called\n");
                dev->hub_ports[w_index-1].change &= ~PORT_STAT_C_CONNECTION;

                switch (dev->status) {
                  case DEVICE1_WAIT_DISCONNECT:
                    dev->status = DEVICE1_DISCONNECTED;
                    SET_TIMER (200);
                    break;
                  case DEVICE2_WAIT_DISCONNECT:
                    dev->status = DEVICE2_DISCONNECTED;
                    SET_TIMER (170);
                    break;
                  case DEVICE3_WAIT_DISCONNECT:
                    dev->status = DEVICE3_DISCONNECTED;
                    SET_TIMER (450);
                    break;
                  case DEVICE4_WAIT_DISCONNECT:
                    dev->status = DEVICE4_DISCONNECTED;
                    SET_TIMER (200);
                    break;
                  case DEVICE5_WAIT_DISCONNECT:
                    dev->status = DEVICE5_DISCONNECTED;
                    SET_TIMER (200);
                    break;
                  default:
                    break;
                }
                value = 0;
                break;
              case 20: /* C_PORT_RESET */
                DBG (dev, "ClearPortFeature C_PORT_RESET called\n");
                dev->hub_ports[w_index-1].change &= ~PORT_STAT_C_RESET;

                switch (dev->status) {
                  case DEVICE1_WAIT_READY:
                    if (w_index == 1)
                      dev->switch_to_port_delayed = w_index;
                    break;
                  case DEVICE2_WAIT_READY:
                    if (w_index == 2)
                      dev->switch_to_port_delayed = w_index;
                    break;
                  case DEVICE3_WAIT_READY:
                    if (w_index == 3)
                      dev->switch_to_port_delayed = w_index;
                    break;
                  case DEVICE4_WAIT_READY:
                    if (w_index == 4)
                      dev->switch_to_port_delayed = w_index;
                    break;
                  case DEVICE5_WAIT_READY:
                    if (w_index == 5)
                      dev->switch_to_port_delayed = w_index;
                    break;
                  case DEVICE6_WAIT_READY:
                    if (w_index == 6)
                      dev->switch_to_port_delayed = w_index;
                    break;
                  default:
                    break;
                }
                /* Delay switching the port because we first need to response
                   to this request with the proper address */
                if (dev->switch_to_port_delayed >= 0)
                  SET_TIMER (0);
                value = 0;
                break;
              case 17: /* C_PORT_ENABLE */
              case 18: /* C_PORT_SUSPEND */
              case 19: /* C_PORT_OVER_CURRENT */
              case 21: /* PORT_TEST */
              case 22: /* PORT_INDICATOR */
                DBG (dev, "ClearPortFeature called\n");
                value = 0;
                break;
              default:
                value = -EINVAL;
                break;
            }
            break;
        }
      }
      break;
    case USB_REQ_GET_STATUS:
      if ((ctrl->bRequestType & USB_TYPE_CLASS) == USB_TYPE_CLASS) {
        u16 status = 0;
        u16 change = 0;

        value = 2 * sizeof (u16);
        switch (ctrl->bRequestType & USB_RECIP_MASK) {
          case USB_RECIP_DEVICE:
            /* GET_HUB_STATUS */
            status = 0;
            change = 0;
            break;
          case USB_RECIP_OTHER:
            /* GET_PORT_STATUS */
            if (w_index == 0 || w_index > 6) {
              DBG (dev, "GetPortstatus : invalid port index %d\n", w_index);
              value = -EINVAL;
              break;
            }
            status = dev->hub_ports[w_index -1].status;
            change = dev->hub_ports[w_index -1].change;
            break;
          default:
            goto unknown;
        }
        if (value > 0) {
          DBG (dev, "GetHub/PortStatus: transmtiting status %d change %d\n",
              status, change);
          status = cpu_to_le16 (status);
          change = cpu_to_le16 (change);
          memcpy(req->buf, &status, sizeof(u16));
          memcpy(req->buf + sizeof(u16), &change, sizeof(u16));
        }
      }
      break;
    default:
    unknown:
      ERROR (dev, "unknown control req%02x.%02x v%04x i%04x l%d\n",
          ctrl->bRequestType, ctrl->bRequest,
          w_value, w_index, w_length);
  }

  /* device either stalls (value < 0) or reports success */
  return value;
}