Example #1
0
Result HcdChannelSendWait(struct UsbDevice *device, 
	struct UsbPipeAddress *pipe, u8 channel, void* buffer, u32 bufferLength, 
	struct UsbDeviceRequest *request, enum PacketId packetId) {
	Result result;
	u32 packets, transfer, tries;
	
	tries = 0;
retry:
	if (tries++ == 3) {
		LOGF("HCD: Failed to send to %s after 3 attempts.\n", UsbGetDescription(device));
		return ErrorTimeout;
	} 

	if ((result = HcdPrepareChannel(device, channel, bufferLength, packetId, pipe)) != OK) {		
		device->Error = ConnectionError;
		LOGF("HCD: Could not prepare data channel to %s.\n", UsbGetDescription(device));
		return result;
	}
		
	transfer = 0;
	do {
		packets = Host->Channel[channel].TransferSize.PacketCount;
		if ((result = HcdChannelSendWaitOne(device, pipe, channel, buffer, bufferLength, transfer, request)) != OK) {
			if (result == ErrorRetry) goto retry;
			return result;
		}
		
		ReadBackReg(&Host->Channel[channel].TransferSize);		
		transfer = bufferLength - Host->Channel[channel].TransferSize.TransferSize;
		if (packets == Host->Channel[channel].TransferSize.PacketCount) break;
	} while (Host->Channel[channel].TransferSize.PacketCount > 0);

	if (packets == Host->Channel[channel].TransferSize.PacketCount) {
		device->Error = ConnectionError;
		LOGF("HCD: Transfer to %s got stuck.\n", UsbGetDescription(device));
		return ErrorDevice;
	}

	if (tries > 1) {
		LOGF("HCD: Transfer to %s succeeded on attempt %d/3.\n", UsbGetDescription(device), tries);
	}

	return OK;
}
Example #2
0
struct KeyboardLeds KeyboardGetLedSupport(u32 keyboardAddress) {
  u32 keyboardNumber;
  struct KeyboardDevice *data;
  
  keyboardNumber = KeyboardIndex(keyboardAddress);
  if (keyboardNumber == 0xffffffff) return (struct KeyboardLeds) { 0, 0, 0, 0, 0, 0, 0, 0 };
  data = (struct KeyboardDevice*)((struct HidDevice*)keyboards[keyboardNumber]->DriverData)->DriverData;
  return data->LedSupport;
}

Result KeyboardPoll(u32 keyboardAddress) {
  u32 keyboardNumber;
  Result result;
  struct KeyboardDevice *data;
  
  keyboardNumber = KeyboardIndex(keyboardAddress);  
  if (keyboardNumber == 0xffffffff) return ErrorDisconnected;
  data = (struct KeyboardDevice*)((struct HidDevice*)keyboards[keyboardNumber]->DriverData)->DriverData;
  if ((result = HidReadDevice(keyboards[keyboardNumber], data->KeyReport->Index)) != OK) {
    if (result != ErrorDisconnected)
      LOGF("KBD: Could not get key report from %s.\n", UsbGetDescription(keyboards[keyboardNumber]));
    return result;
  }

  if (data->KeyFields[0] != NULL)
    data->Modifiers.LeftControl = data->KeyFields[0]->Value.Bool;
  if (data->KeyFields[1] != NULL)
    data->Modifiers.LeftShift = data->KeyFields[1]->Value.Bool;
  if (data->KeyFields[2] != NULL)
    data->Modifiers.LeftAlt = data->KeyFields[2]->Value.Bool;
  if (data->KeyFields[3] != NULL)
    data->Modifiers.LeftGui = data->KeyFields[3]->Value.Bool;
  if (data->KeyFields[4] != NULL)
    data->Modifiers.RightControl = data->KeyFields[4]->Value.Bool;
  if (data->KeyFields[5] != NULL)
    data->Modifiers.RightShift = data->KeyFields[5]->Value.Bool;
  if (data->KeyFields[6] != NULL)
    data->Modifiers.RightAlt = data->KeyFields[6]->Value.Bool;
  if (data->KeyFields[7] != NULL)
    data->Modifiers.RightGui = data->KeyFields[7]->Value.Bool;
  if (data->KeyFields[8] != NULL) {
    if (HidGetFieldValue(data->KeyFields[8], 0) != KeyboardErrorRollOver) {
      data->KeyCount = 0;
      for (u32 i = 0; i < KeyboardMaxKeys && i < data->KeyFields[8]->Count; i++) {
        if ((data->Keys[i] = HidGetFieldValue(data->KeyFields[8], i)) + (u16)data->KeyFields[8]->Usage.Keyboard != 0)
          data->KeyCount++;
      }
    }
  }

  return OK;
}
Example #3
0
Result HcdSumbitControlMessage(struct UsbDevice *device, 
	struct UsbPipeAddress pipe, void* buffer, u32 bufferLength,
	struct UsbDeviceRequest *request) {
	Result result;
	struct UsbPipeAddress tempPipe;
	if (pipe.Device == RootHubDeviceNumber) {
		return HcdProcessRootHubMessage(device, pipe, buffer, bufferLength, request);
	}

	device->Error = Processing;
	device->LastTransfer = 0;
			
	// Setup
	tempPipe.Speed = pipe.Speed;
	tempPipe.Device = pipe.Device;
	tempPipe.EndPoint = pipe.EndPoint;
	tempPipe.MaxSize = pipe.MaxSize;
	tempPipe.Type = Control;
	tempPipe.Direction = Out;
	
	if ((result = HcdChannelSendWait(device, &tempPipe, 0, request, 8, request, Setup)) != OK) {		
		LOGF("HCD: Could not send SETUP to %s.\n", UsbGetDescription(device));
		return OK;
	}

	// Data
	if (buffer != NULL) {
		if (pipe.Direction == Out) {
			MemoryCopy(databuffer, buffer, bufferLength);
		}
		tempPipe.Speed = pipe.Speed;
		tempPipe.Device = pipe.Device;
		tempPipe.EndPoint = pipe.EndPoint;
		tempPipe.MaxSize = pipe.MaxSize;
		tempPipe.Type = Control;
		tempPipe.Direction = pipe.Direction;
		
		if ((result = HcdChannelSendWait(device, &tempPipe, 0, databuffer, bufferLength, request, Data1)) != OK) {		
			LOGF("HCD: Could not send DATA to %s.\n", UsbGetDescription(device));
			return OK;
		}
						
		ReadBackReg(&Host->Channel[0].TransferSize);
		if (pipe.Direction == In) {
			if (Host->Channel[0].TransferSize.TransferSize <= bufferLength)
				device->LastTransfer = bufferLength - Host->Channel[0].TransferSize.TransferSize;
			else{
				LOG_DEBUGF("HCD: Weird transfer.. %d/%d bytes received.\n", Host->Channel[0].TransferSize.TransferSize, bufferLength);
				LOG_DEBUGF("HCD: Message %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x ...\n", 
					((u8*)databuffer)[0x0],((u8*)databuffer)[0x1],((u8*)databuffer)[0x2],((u8*)databuffer)[0x3],
					((u8*)databuffer)[0x4],((u8*)databuffer)[0x5],((u8*)databuffer)[0x6],((u8*)databuffer)[0x7],
					((u8*)databuffer)[0x8],((u8*)databuffer)[0x9],((u8*)databuffer)[0xa],((u8*)databuffer)[0xb],
					((u8*)databuffer)[0xc],((u8*)databuffer)[0xd],((u8*)databuffer)[0xe],((u8*)databuffer)[0xf]);
				device->LastTransfer = bufferLength;
			}
			MemoryCopy(buffer, databuffer, device->LastTransfer);
		}
		else {
			device->LastTransfer = bufferLength;
		}
	}

	// Status
	tempPipe.Speed = pipe.Speed;
	tempPipe.Device = pipe.Device;
	tempPipe.EndPoint = pipe.EndPoint;
	tempPipe.MaxSize = pipe.MaxSize;
	tempPipe.Type = Control;
	tempPipe.Direction = ((bufferLength == 0) || pipe.Direction == Out) ? In : Out;
	
	if ((result = HcdChannelSendWait(device, &tempPipe, 0, databuffer, 0, request, Data1)) != OK) {		
		LOGF("HCD: Could not send STATUS to %s.\n", UsbGetDescription(device));
		return OK;
	}

	ReadBackReg(&Host->Channel[0].TransferSize);
	if (Host->Channel[0].TransferSize.TransferSize != 0)
		LOG_DEBUGF("HCD: Warning non zero status transfer! %d.\n", Host->Channel[0].TransferSize.TransferSize);

	device->Error = NoError;

	return OK;
}
Example #4
0
Result HcdChannelSendWaitOne(struct UsbDevice *device, 
	struct UsbPipeAddress *pipe, u8 channel, void* buffer, u32 bufferLength, u32 bufferOffset,
	struct UsbDeviceRequest *request) {
	Result result;
	u32 timeout, tries, globalTries, actualTries;
	
	for (globalTries = 0, actualTries = 0; globalTries < 3 && actualTries < 10; globalTries++, actualTries++) {
		SetReg(&Host->Channel[channel].Interrupt);
		WriteThroughReg(&Host->Channel[channel].Interrupt);
		ReadBackReg(&Host->Channel[channel].TransferSize);
		ReadBackReg(&Host->Channel[channel].SplitControl);
						
		HcdTransmitChannel(channel, (u8*)buffer + bufferOffset);

		timeout = 0;
		do {
			if (timeout++ == RequestTimeout) {
				LOGF("HCD: Request to %s has timed out.\n", UsbGetDescription(device));
				device->Error = ConnectionError;
				return ErrorTimeout;
			}
			ReadBackReg(&Host->Channel[channel].Interrupt);
			if (!Host->Channel[channel].Interrupt.Halt) MicroDelay(10);
			else break;
		} while (true);
		ReadBackReg(&Host->Channel[channel].TransferSize);
		
		if (Host->Channel[channel].SplitControl.SplitEnable) {
			if (Host->Channel[channel].Interrupt.Acknowledgement) {
				for (tries = 0; tries < 3; tries++) {
					SetReg(&Host->Channel[channel].Interrupt);
					WriteThroughReg(&Host->Channel[channel].Interrupt);

					ReadBackReg(&Host->Channel[channel].SplitControl);
					Host->Channel[channel].SplitControl.CompleteSplit = true;
					WriteThroughReg(&Host->Channel[channel].SplitControl);
					
					Host->Channel[channel].Characteristic.Enable = true;
					Host->Channel[channel].Characteristic.Disable = false;
					WriteThroughReg(&Host->Channel[channel].Characteristic);

					timeout = 0;
					do {
						if (timeout++ == RequestTimeout) {
							LOGF("HCD: Request split completion to %s has timed out.\n", UsbGetDescription(device));
							device->Error = ConnectionError;
							return ErrorTimeout;
						}
						ReadBackReg(&Host->Channel[channel].Interrupt);
						if (!Host->Channel[channel].Interrupt.Halt) MicroDelay(100);
						else break;
					} while (true);
					if (!Host->Channel[channel].Interrupt.NotYet) break;
				}

				if (tries == 3) {
					MicroDelay(25000);
					continue;
				} else if (Host->Channel[channel].Interrupt.NegativeAcknowledgement) {
					globalTries--;
					MicroDelay(25000);
					continue;
				} else if (Host->Channel[channel].Interrupt.TransactionError) {
					MicroDelay(25000);
					continue;
				}
	
				if ((result = HcdChannelInterruptToError(device, Host->Channel[channel].Interrupt, false)) != OK) {
					LOG_DEBUGF("HCD: Control message to %#x: %02x%02x%02x%02x %02x%02x%02x%02x.\n", *(u32*)pipe, 
						((u8*)request)[0], ((u8*)request)[1], ((u8*)request)[2], ((u8*)request)[3],
						((u8*)request)[4], ((u8*)request)[5], ((u8*)request)[6], ((u8*)request)[7]);
					LOGF("HCD: Request split completion to %s failed.\n", UsbGetDescription(device));
					return result;
				}
			} else if (Host->Channel[channel].Interrupt.NegativeAcknowledgement) {
				globalTries--;
				MicroDelay(25000);
				continue;
			} else if (Host->Channel[channel].Interrupt.TransactionError) {
				MicroDelay(25000);
				continue;
			}				
		} else {				
			if ((result = HcdChannelInterruptToError(device, Host->Channel[channel].Interrupt, !Host->Channel[channel].SplitControl.SplitEnable)) != OK) {
				LOG_DEBUGF("HCD: Control message to %#x: %02x%02x%02x%02x %02x%02x%02x%02x.\n", *(u32*)pipe, 
					((u8*)request)[0], ((u8*)request)[1], ((u8*)request)[2], ((u8*)request)[3],
					((u8*)request)[4], ((u8*)request)[5], ((u8*)request)[6], ((u8*)request)[7]);
				LOGF("HCD: Request to %s failed.\n", UsbGetDescription(device));
				return ErrorRetry;
			}
		}

		break;
	}

	if (globalTries == 3 || actualTries == 10) {
		LOGF("HCD: Request to %s has failed 3 times.\n", UsbGetDescription(device));
		if ((result = HcdChannelInterruptToError(device, Host->Channel[channel].Interrupt, !Host->Channel[channel].SplitControl.SplitEnable)) != OK) {
			LOG_DEBUGF("HCD: Control message to %#x: %02x%02x%02x%02x %02x%02x%02x%02x.\n", *(u32*)pipe, 
				((u8*)request)[0], ((u8*)request)[1], ((u8*)request)[2], ((u8*)request)[3],
				((u8*)request)[4], ((u8*)request)[5], ((u8*)request)[6], ((u8*)request)[7]);
			LOGF("HCD: Request to %s failed.\n", UsbGetDescription(device));
			return result;
		}
		device->Error = ConnectionError;
		return ErrorTimeout;
	}

	return OK;
}
Example #5
0
Result KeyboardAttach(struct UsbDevice *device, u32 interface __attribute__((unused))) {
  u32 keyboardNumber;
  struct HidDevice *hidData;
  struct KeyboardDevice *data;
  struct HidParserResult *parse;

  if ((KeyboardMaxKeyboards & 3) != 0) {
    LOG("KBD: Warning! KeyboardMaxKeyboards not a multiple of 4. The driver wasn't built for this!\n");
  }
  if (keyboardCount == KeyboardMaxKeyboards) {
    LOGF("KBD: %s not connected. Too many keyboards connected (%d/%d). Change KeyboardMaxKeyboards in device.keyboard.c to allow more.\n", UsbGetDescription(device), keyboardCount, KeyboardMaxKeyboards);
    return ErrorIncompatible;
  }
  
  hidData = (struct HidDevice*)device->DriverData;
  if (hidData->Header.DeviceDriver != DeviceDriverHid) {
    LOGF("KBD: %s isn't a HID device. The keyboard driver is built upon the HID driver.\n", UsbGetDescription(device));
    return ErrorIncompatible;
  }

  parse = hidData->ParserResult;
  if ((parse->Application.Page != GenericDesktopControl && parse->Application.Page != Undefined) ||
    parse->Application.Desktop != DesktopKeyboard) {
    LOGF("KBD: %s doesn't seem to be a keyboard (%x != %x || %x != %x)...\n", UsbGetDescription(device), parse->Application.Page, GenericDesktopControl, parse->Application.Desktop, DesktopKeyboard);
    return ErrorIncompatible;
  }
  if (parse->ReportCount < 1) {
    LOGF("KBD: %s doesn't have enough outputs to be a keyboard.\n", UsbGetDescription(device));
    return ErrorIncompatible;
  }
  hidData->HidDetached = KeyboardDetached;
  hidData->HidDeallocate = KeyboardDeallocate;
  if ((hidData->DriverData = MemoryAllocate(sizeof(struct KeyboardDevice))) == NULL) {
    LOGF("KBD: Not enough memory to allocate keyboard %s.\n", UsbGetDescription(device));
    return ErrorMemory;
  }
  data = (struct KeyboardDevice*)hidData->DriverData;
  data->Header.DeviceDriver = DeviceDriverKeyboard;
  data->Header.DataSize = sizeof(struct KeyboardDevice);
  data->Index = keyboardNumber = 0xffffffff;
  for (u32 i = 0; i < KeyboardMaxKeyboards; i++) {
    if (keyboardAddresses[i] == 0) {
      data->Index = keyboardNumber = i;
      keyboardAddresses[i] = device->Number;
      keyboardCount++;
      break;
    }
  }

  if (keyboardNumber == 0xffffffff) {
    LOG("KBD: PANIC! Driver in inconsistent state! KeyboardCount is inaccurate.\n");
    KeyboardDeallocate(device);
    return ErrorGeneral;
  }

  keyboards[keyboardNumber] = device;
  for (u32 i = 0; i < KeyboardMaxKeys; i++)
    data->Keys[i] = 0;
  *(u8*)&data->Modifiers = 0;
  *(u8*)&data->LedSupport = 0;

  for (u32 i = 0; i < 9; i++)
    data->KeyFields[i] = NULL;
  for (u32 i = 0; i < 8; i++)
    data->LedFields[i] = NULL;
  data->LedReport = NULL;
  data->KeyReport = NULL;

  for (u32 i = 0; i < parse->ReportCount; i++) {
    LOG_DEBUGF("KBD: type %x report %d. %d fields.\n", parse->Report[i]->Type, i, parse->Report[i]->FieldCount);
    if (parse->Report[i]->Type == Input && 
      data->KeyReport == NULL) {
      LOG_DEBUGF("KBD: Output report %d. %d fields.\n", i, parse->Report[i]->FieldCount);
      data->KeyReport = parse->Report[i];
      for (u32 j = 0; j < parse->Report[i]->FieldCount; j++) {
        if (parse->Report[i]->Fields[j].Usage.Page == KeyboardControl || parse->Report[i]->Fields[j].Usage.Page == Undefined) {
          if (parse->Report[i]->Fields[j].Attributes.Variable) {
            if (parse->Report[i]->Fields[j].Usage.Keyboard >= KeyboardLeftControl
              && parse->Report[i]->Fields[j].Usage.Keyboard <= KeyboardRightGui)
              LOG_DEBUGF("KBD: Modifier %d detected! Offset=%x, size=%x\n", parse->Report[i]->Fields[j].Usage.Keyboard, parse->Report[i]->Fields[j].Offset, parse->Report[i]->Fields[j].Size);
              data->KeyFields[(u16)parse->Report[i]->Fields[j].Usage.Keyboard - (u16)KeyboardLeftControl] = 
                &parse->Report[i]->Fields[j];
          } else {
            LOG_DEBUG("KBD: Key input detected!\n");
            data->KeyFields[8] = &parse->Report[i]->Fields[j];
          }
        }
      }
    } else if (parse->Report[i]->Type == Output && 
      data->LedReport == NULL) {
      data->LedReport = parse->Report[i];
      LOG_DEBUGF("KBD: Input report %d. %d fields.\n", i, parse->Report[i]->FieldCount);
      for (u32 j = 0; j < parse->Report[i]->FieldCount; j++) {
        if (parse->Report[i]->Fields[j].Usage.Page == Led) {
          switch (parse->Report[i]->Fields[j].Usage.Led) {
          case LedNumberLock:
            LOG_DEBUG("KBD: Number lock LED detected!\n");
            data->LedFields[0] = &parse->Report[i]->Fields[j];
            data->LedSupport.NumberLock = true;
            break;
          case LedCapsLock:
            LOG_DEBUG("KBD: Caps lock LED detected!\n");
            data->LedFields[1] = &parse->Report[i]->Fields[j];
            data->LedSupport.CapsLock = true;
            break;
          case LedScrollLock:
            LOG_DEBUG("KBD: Scroll lock LED detected!\n");
            data->LedFields[2] = &parse->Report[i]->Fields[j];
            data->LedSupport.ScrollLock = true;
            break;
          case LedCompose:
            LOG_DEBUG("KBD: Compose LED detected!\n");
            data->LedFields[3] = &parse->Report[i]->Fields[j];
            data->LedSupport.Compose = true;
            break;
          case LedKana:
            LOG_DEBUG("KBD: Kana LED detected!\n");
            data->LedFields[4] = &parse->Report[i]->Fields[j];
            data->LedSupport.Kana = true;
            break;
          case LedPower:
            LOG_DEBUG("KBD: Power LED detected!\n");
            data->LedFields[5] = &parse->Report[i]->Fields[j];
            data->LedSupport.Power = true;
            break;
          case LedShift:
            LOG_DEBUG("KBD: Shift LED detected!\n");
            data->LedFields[6] = &parse->Report[i]->Fields[j];
            data->LedSupport.Shift = true;
            break;
          case LedMute:
            LOG_DEBUG("KBD: Mute LED detected!\n");
            data->LedFields[7] = &parse->Report[i]->Fields[j];
            data->LedSupport.Mute = true;
            break;
          default: break; 
          }
        }
      }
    }
  }

  LOG_DEBUGF("KBD: New keyboard assigned %d!\n", device->Number);

  return OK;
}