Пример #1
0
static void
usb_send_desc(setup_t *sp)
{
  // initialize with:
  //  * len = requested length
  //  * dsc = configuration descriptor
  //  * wTotalLength = wTotalLength field of configuration descriptor
  uint8_t     len = HTOUS(sp->asdescreq.len);
  usbdescr_t *dsc = (usbdescr_t*) &(usbdev.usbdesc[((usbdescr_t*) usbdev.usbdesc)->bLength]);
  uint16_t    wTotalLength = HTOUS(*(uint16_t*) dsc->buf);
  size_t      i;

  switch(sp->asdescreq.val)
  {
    case DEVICE_DESCRIPTOR:
      PUTS("dev_desc\n");
      dsc = (usbdescr_t*) usbdev.usbdesc;
      len = dsc->bLength;
      break;

    case CONFIGURATION_DESCRIPTOR:
      PUTS("conf_desc\n");
      len = MIN(len, wTotalLength);
      break;

    case STRING_DESCRIPTOR:
      PUTS("str_desc\n");
      dsc = (usbdescr_t*) &dsc->buf[wTotalLength-sizeof(usbdescr_t)]; /* at the first string now */
      for(i=0; i<sp->asdescreq.idx && dsc->bDescriptorType==STRING_DESCRIPTOR; i++)
          dsc = (usbdescr_t*) &dsc->buf[dsc->bLength-sizeof(usbdescr_t)];
      len = dsc->bLength;
      break;

    default:
      PUTS("unknown setup request\n");
      STALLEP0();
  }

  {
  uint8_t wlen = MIN(64, len),
          *pt  = (uint8_t*) dsc;
  reg_t   st   = {0x00};

  do
  {
    wlen = MIN(64, len);

    /* wait until asserted */
    do { rreg(EPIRQ, &st); } while( !st.EPIRQ.IN0BAVIRQ );

    /* writing to EP0, also clrs irq */
    wregn(EP0FIFO, pt, wlen, false);
    wregn(EP0BC, &wlen, sizeof(uint8_t), len<64);

    len -= wlen;
    pt  += wlen;
  } while(len>0);
  }
}
Пример #2
0
static bool
usb_setup(setup_t *sp)
{
  switch(sp->reqtype.type)
  {
    case 0x00: PUTS("usb: std_req - "); return std_req(sp); break;
    case 0x01: PUTS("usb: class_req - "); break;
    case 0x02: PUTS("usb: vendor_req - "); break;
    default:   GDB2_PUTS("unknown req - "); STALLEP0();
  }

  GDB2_PUTS(".\n");
  return false;
}
Пример #3
0
static void
get_status(setup_t *sp)
{
  uint8_t len = sizeof(sp->asstatresp);
  reg_t st = {0x00};

  switch(sp->reqtype.recp)
  {
    case TO_DEVICE:
      sp->asstatresp = (usbdev.status.rwu_enabled)<<9 |
                       (usbdev.status.self_powered)<<8;
      break;
    case TO_ENDPOINT: /* XXX: for endpoint the stall status should be returned */
    case TO_INTERFACE:
      sp->asstatresp = 0x0000;
      break;
    default:
      STALLEP0();
  }

  do { rreg(EPIRQ, &st); } while( !st.EPIRQ.IN0BAVIRQ );
  wregn(EP0FIFO, (uint8_t*) &sp->asstatresp, len, false);
  wregn(EP0BC, &len, sizeof(len), true);
}
Пример #4
0
/**
 * Looks into the SETUPDAT data and dispatches to the callback handlers.
 *
 * Note that this code will handshake the packet for all callbacks except
 * handle_vendorcommand(). This code *used* to handshake those too, but as it
 * is not required by the specification to do so (for packets with a DATA
 * segment) it doesn't do it anymore.
 */
void handle_setupdata() {
    BOOL handshake = TRUE;
    //printf ( "Handle setupdat: %02x\n", SETUPDAT[1] );

    switch ( SETUPDAT[1] ) {

        case GET_STATUS:
            if (!handle_get_status())
                STALLEP0();
            break;
        case CLEAR_FEATURE:
            if (!handle_clear_feature()) {
                STALLEP0();
            }
            break;
        case SET_FEATURE:
            if (!handle_set_feature()) {
                STALLEP0();
            }
            break;
        case GET_DESCRIPTOR:
            handle_get_descriptor();
            break;
        case GET_CONFIGURATION:            
            EP0BUF[0] = handle_get_configuration();
            EP0BCH=0;
            EP0BCL=1;
            break;
        case SET_CONFIGURATION:
            // user callback
            if( !handle_set_configuration(SETUPDAT[2])) {
                STALLEP0();
            }
            break;
        case GET_INTERFACE:
            {
                BYTE alt_ifc;
                if (!handle_get_interface(SETUPDAT[4],&alt_ifc)) {
                    STALLEP0();
                } else {
                 EP0BUF[0] = alt_ifc;
                 EP0BCH=0;
                 EP0BCL=1;
                }
            }
            break;
        case SET_INTERFACE:
            // user callback
            if ( !handle_set_interface(SETUPDAT[4],SETUPDAT[2])) {
                STALLEP0();
            }
            break;
        default:
            if (handle_vendorcommand(SETUPDAT[1])) {
                handshake = FALSE;
            } else {
                printf ( "Unhandled Vendor Command: %02x\n" , SETUPDAT[1] );
                STALLEP0();
            }
    }

    // do the handshake
    if(handshake) {
        EP0CS |= bmHSNAK;
    }
}
Пример #5
0
static bool
std_req(setup_t *sp)
{
  switch(sp->req)
  {
    case SR_SET_ADDRESS:
      PUTS("set_addr\n");
      rregn(FNADDR, NULL, 0, true);
      break;
    case SR_GET_DESCRIPTOR:
      PUTS("get_desc: ");
      usb_send_desc(sp);
      break;
    case SR_SET_FEATURE:
      /* this either sets that RWU is to be enabled or to halt an EP,
       * which is mandatory for bulk and interrupt EPs */
      PUTS("set_feature\n");
      break;
    case SR_CLEAR_FEATURE:
      /* clear one of the features which have been set by SET_FEATURE */
      PUTS("clear_feature\n");
      break;
    case SR_GET_STATUS:
      PUTS("get_status\n");
      get_status(sp);
      break;
    case SR_SET_INTERFACE:
      /* this is used to set alternative interfaces. For example when
       * the CDC device will be put up */
      PUTS("setif");
      ACK();
      break;
    case SR_GET_INTERFACE:
      PUTS("getif");
      /* always report the same alternative: 1 */
      {
        uint8_t i = 0x01;
        reg_t st = {0x00};
        do { rreg(EPIRQ, &st); } while( !st.EPIRQ.IN0BAVIRQ );
        wregn(EP0FIFO, &i, sizeof(uint8_t), false);
        i=sizeof(uint8_t);
        wregn(EP0BC, &i, i, true);
      }
      break;
    case SR_SET_CONFIGURATION:
      PUTS("set_conf\n");
      usbdev.status.configuration = sp->asconfreq.conf;
      ACK();
      return true;
      break;
    case SR_GET_CONFIGURATION:
      PUTS("get_conf\n");
      {
        uint8_t len = sizeof(usbdev.status.configuration);
        reg_t st = {0x00};
        do { rreg(EPIRQ, &st); } while( !st.EPIRQ.IN0BAVIRQ );
        wregn(EP0FIFO, &usbdev.status.configuration, len, false);
        wregn(EP0BC, &len, sizeof(len), true);
      }
      break;
    default:
      PUTS("unknown std_req()");
      STALLEP0();
  }

  return false;
}