Quelltext /~heha/ewa/Motor/Maxmaus9.zip/usblib/usbd.cpp

// TITLE: Enumeration code to handle all endpoint zero traffic
#include "usbd.h"
#include <sysctl.h>
#include <usb.h>

namespace usb{

bool tDevice::Init() {
  config = 0;
  devstat = 0;

  USBDevMode(USB_BASE);        // Force device mode
  USBIntStatusControl(USB_BASE);
  USBIntStatusEndpoint(USB_BASE);
  USBIntEnableControl(USB_BASE,
		  USB_INTCTRL_RESET
		| USB_INTCTRL_DISCONNECT
		| USB_INTCTRL_RESUME
		| USB_INTCTRL_SUSPEND
		| USB_INTCTRL_SOF);
  USBIntEnableEndpoint(USB_BASE, USB_INTEP_ALL);
  USBDevConnect(USB_BASE);
  return true;
}

void tDevice::Term() {
  USBIntDisableControl(USB_BASE, USB_INTCTRL_ALL);
  USBIntDisableEndpoint(USB_BASE, USB_INTEP_ALL);
  USBDevDisconnect(USB_BASE);
  USBIntStatusControl(USB_BASE);
  USBIntStatusEndpoint(USB_BASE);
}

void tDevice::SendDataEP0(const uint8_t *data, unsigned size) {
  while (size) {
    unsigned sz=size>64?64:size;
    if (USBEndpointDataPut(USB_BASE, 0, const_cast<uint8_t*>(data), sz)) {
      idle();
      if (USBIntStatusControl(USB_BASE)&USB_INTCTRL_RESET) return;
    }
    USBEndpointDataSend(USB_BASE, 0, sz==64 ? USB_TRANS_IN : USB_TRANS_IN_LAST);
    data+=sz;
    size-=sz;
  }
}

void tDevice::SendDataEP0(const uint8_t *data, unsigned size, const tRequest&rq) {
  rq.limitLength(size);
  SendDataEP0(data, size);
}

void tDevice::pollEP0() {
  tRequest rq;
  uint32_t ui32Size = sizeof rq;
    // Get the data from the USB controller end point 0.
  USBEndpointDataGet(USB_BASE, 0, rq,&ui32Size);
    // If there was a null setup packet then just return.
  if (!ui32Size) return;
  USBDevEndpointDataAck(USB_BASE, 0, !(rq.bmRequestType&0x80));
  uint8_t answer[2]={0,0};
  switch (rq.wRequest()) {
    case 0x0080: {	// GetStatus-Device
      answer[0]=devstat;
      SendDataEP0(answer,2);
    }return;
    case 0x0081: {	// GetStatus-Interface(wIndexL)
      SendDataEP0(answer,2);
    }return;
    case 0x0082: {	// GetStatus-Endpoint(wIndexL)
      if (rq.wIndexL != 0x81) goto stall;
      //TODO: Stall-Zustand von EP1IN abfragen
      SendDataEP0(answer,2);
    }return;

    case 0x0100: {	// ClearFeature-Device
      if (rq.wValueL != 1) goto stall;
      devstat &= ~2;	// Clear the remote wake up state.
    }return;
    case 0x0102: {	// ClearFeature-Endpoint(wIndexL)
      if (rq.wIndexL != 0x81) goto stall;	// Nur EP1IN
      if (rq.wValueL != 0) goto stall;	// nur HALT
      USBDevEndpointStallClear(USB_BASE,1<<4,USB_EP_DEV_IN);
      USBEndpointDataToggleClear(USB_BASE,1<<4,USB_EP_DEV_IN);
    }return;

    case 0x0300: {	// SetFeature-Device
      if (rq.wValueL != 1) goto stall;
      devstat |= 2;	// Set the remote wake up state
    }return;
    case 0x0302: {	// SetFeature-Endpoint(wIndexL)
      if (rq.wIndexL != 0x81) goto stall;	// Nur EP1IN
      if (rq.wValueL != 0) goto stall;	// nur HALT
      USBDevEndpointStall(USB_BASE,1<<4,USB_EP_DEV_IN);
    }return;

    case 0x0500: {	// SetAddress-Device
      while (!(USBIntStatusEndpoint(USB_BASE)&USB_INTEP_0)) {
	idle();
        if (USBIntStatusControl(USB_BASE)&USB_INTCTRL_RESET) return;
      };
      USBDevAddrSet(USB_BASE,rq.wValueL);
    }return;

    case 0x0680:	// GetDescriptor-Device (für HID-Deskriptor aus UsbTreeView)
    case 0x0681: {	// GetDescriptor-Interface (für HID-Deskriptor aus Windows)
// Need to ACK the data on end point 0 without setting last data as there will be a data phase.
      if (cbGetDescriptor(rq)) return;
    }goto stall;

    case 0x0700: goto stall;	// SetDescriptor-Device

    case 0x0880: {	// GetConfig-Device
      answer[0] = config;
      SendDataEP0(answer,1);
    }return;

    case 0x0900: {	// SetConfig-Device
      if (rq.wValueL>1) goto stall;	// nur 0 oder 1 erlaubt
      if ((config = rq.wValueL)) {
      // Konfiguriere EP1IN
        USBDevEndpointConfigSet(USB_BASE,1<<4,64,USB_EP_MODE_INT/*|USB_EP_AUTO_SET*/);
      // EP0 verwendet die ersten 64 Bytes, EP1 kommt danach:
        USBFIFOConfigSet(USB_BASE,1<<4,64,64,USB_EP_DEV_IN);
      }
    }return;

    case 0x0A81: {	// GetInterface-Interface(wIndexL)
      if (rq.wIndexL) goto stall;
      SendDataEP0(answer,1);	// Einfaches Beispiel hat nur eine Alternate Setting
    }return;

    case 0x0B01: {	// SetInterface-Interface(wIndexL)
      // bmRequestType=0x01, wIndexL=Interface, wValueL=AltSetting, wLength=0
      if (rq.wIndexL) goto stall;
      if (rq.wValueL) goto stall;
    }return;

    case 0x0C82: goto stall;	// SyncFrame-Endpoint(wIndexL)
	// bmRequestType=0x82, wIndexL=Endpoint, wLength=2: Antwort = FrameNumber
    default: if (cbRequestHandler(rq)) return;
  }
stall:
  USBDevEndpointStall(USB_BASE, 0, USB_EP_DEV_OUT);
}


void tDevice::poll() {
  if (!this) {
    USBDevDisconnect(USB_BASE);
    return;
  }
  uint32_t IntStatusEP,sta = USBIntStatus(USB_BASE,&IntStatusEP);
  if (sta & USB_INTCTRL_RESET) onReset();
  if (sta & USB_INTCTRL_DISCONNECT) onDisconnect();
  if (sta & USB_INTCTRL_SOF) onSOF();
  if (IntStatusEP & USB_INTEP_0) {
    uint32_t sta = USBEndpointStatus(USB_BASE, 0);
    if (sta & USB_DEV_EP0_OUT_PKTRDY) pollEP0();
//        USBDevEndpointDataAck(USB_BASE, USB_EP_0, true);
    if (sta & USB_DEV_EP0_SENT_STALL)
     USBDevEndpointStatusClear(USB_BASE, USB_EP_0, USB_DEV_EP0_SENT_STALL);
  }
}

}
Vorgefundene Kodierung: UTF-80