uint8_t PTP_Transaction(uint16_t opCode, uint8_t receive_data, uint8_t paramCount, uint32_t *params, uint8_t dataBytes, uint8_t *data) { if(PTP_Error) return PTP_RETURN_ERROR; if(PTP_Bytes_Remaining > 0) return PTP_FetchData(0); uint8_t err; PTP_Run_Task = 0; // Pause task while we're busy with the transaction if(paramCount > 0 && params) err = SI_Host_SendCommand(&DigitalCamera_SI_Interface, CPU_TO_LE16(opCode), paramCount, params); else err = SI_Host_SendCommand(&DigitalCamera_SI_Interface, CPU_TO_LE16(opCode), 0, NULL); if(!err && dataBytes > 0 && data) // send data { DigitalCamera_SI_Interface.State.TransactionID--; PIMA_Block = (PIMA_Container_t) { .DataLength = CPU_TO_LE32(PIMA_DATA_SIZE(dataBytes)), .Type = CPU_TO_LE16(PIMA_CONTAINER_DataBlock), .Code = CPU_TO_LE16(opCode) }; memcpy(&PIMA_Block.Params, data, dataBytes); err = SI_Host_SendBlockHeader(&DigitalCamera_SI_Interface, &PIMA_Block); }
uint8_t SI_Host_OpenSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) { if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive)) return HOST_SENDCONTROL_DeviceDisconnected; uint8_t ErrorCode; SIInterfaceInfo->State.TransactionID = 0; SIInterfaceInfo->State.IsSessionOpen = false; PIMA_Container_t PIMABlock = (PIMA_Container_t) { .DataLength = PIMA_COMMAND_SIZE(1), .Type = PIMA_CONTAINER_CommandBlock, .Code = 0x1002, .Params = {1}, }; if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError) return ErrorCode; if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError) return ErrorCode; if ((PIMABlock.Type != PIMA_CONTAINER_ResponseBlock) || (PIMABlock.Code != 0x2001)) return SI_ERROR_LOGICAL_CMD_FAILED; SIInterfaceInfo->State.IsSessionOpen = true; return PIPE_RWSTREAM_NoError; } uint8_t SI_Host_CloseSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) { if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive)) return HOST_SENDCONTROL_DeviceDisconnected; uint8_t ErrorCode; PIMA_Container_t PIMABlock = (PIMA_Container_t) { .DataLength = PIMA_COMMAND_SIZE(1), .Type = PIMA_CONTAINER_CommandBlock, .Code = 0x1003, .Params = {1}, }; if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError) return ErrorCode; if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError) return ErrorCode; SIInterfaceInfo->State.IsSessionOpen = false; if ((PIMABlock.Type != PIMA_CONTAINER_ResponseBlock) || (PIMABlock.Code != 0x2001)) return SI_ERROR_LOGICAL_CMD_FAILED; return PIPE_RWSTREAM_NoError; } uint8_t SI_Host_SendCommand(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, const uint16_t Operation, const uint8_t TotalParams, uint32_t* const Params) { if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive)) return HOST_SENDCONTROL_DeviceDisconnected; uint8_t ErrorCode; PIMA_Container_t PIMABlock = (PIMA_Container_t) { .DataLength = PIMA_COMMAND_SIZE(TotalParams), .Type = PIMA_CONTAINER_CommandBlock, .Code = Operation, }; memcpy(&PIMABlock.Params, Params, sizeof(uint32_t) * TotalParams); if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError) return ErrorCode; return PIPE_RWSTREAM_NoError; } uint8_t SI_Host_ReceiveResponse(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) { uint8_t ErrorCode; PIMA_Container_t PIMABlock; if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive)) return HOST_SENDCONTROL_DeviceDisconnected; if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError) return ErrorCode; if ((PIMABlock.Type != PIMA_CONTAINER_ResponseBlock) || (PIMABlock.Code != 0x2001)) return SI_ERROR_LOGICAL_CMD_FAILED; return PIPE_RWSTREAM_NoError; }
uint8_t SI_Host_OpenSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) { uint8_t portnum = SIInterfaceInfo->Config.PortNumber; if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive)) return PIPE_RWSTREAM_DeviceDisconnected; uint8_t ErrorCode; SIInterfaceInfo->State.TransactionID = 0; SIInterfaceInfo->State.IsSessionOpen = false; PIMA_Container_t PIMABlock = (PIMA_Container_t) { .DataLength = CPU_TO_LE32(PIMA_COMMAND_SIZE(1)), .Type = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock), .Code = CPU_TO_LE16(0x1002), .Params = {CPU_TO_LE32(1)}, }; if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError) return ErrorCode; if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError) return ErrorCode; if ((PIMABlock.Type != CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock)) || (PIMABlock.Code != CPU_TO_LE16(0x2001))) return SI_ERROR_LOGICAL_CMD_FAILED; SIInterfaceInfo->State.IsSessionOpen = true; return PIPE_RWSTREAM_NoError; } uint8_t SI_Host_CloseSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) { uint8_t portnum = SIInterfaceInfo->Config.PortNumber; if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive)) return PIPE_RWSTREAM_DeviceDisconnected; uint8_t ErrorCode; PIMA_Container_t PIMABlock = (PIMA_Container_t) { .DataLength = CPU_TO_LE32(PIMA_COMMAND_SIZE(1)), .Type = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock), .Code = CPU_TO_LE16(0x1003), .Params = {CPU_TO_LE32(1)}, }; if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError) return ErrorCode; if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError) return ErrorCode; SIInterfaceInfo->State.IsSessionOpen = false; if ((PIMABlock.Type != CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock)) || (PIMABlock.Code != CPU_TO_LE16(0x2001))) return SI_ERROR_LOGICAL_CMD_FAILED; return PIPE_RWSTREAM_NoError; } uint8_t SI_Host_SendCommand(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, const uint16_t Operation, const uint8_t TotalParams, uint32_t* const Params) { uint8_t portnum = SIInterfaceInfo->Config.PortNumber; if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive)) return PIPE_RWSTREAM_DeviceDisconnected; uint8_t ErrorCode; PIMA_Container_t PIMABlock = (PIMA_Container_t) { .DataLength = cpu_to_le32(PIMA_COMMAND_SIZE(TotalParams)), .Type = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock), .Code = cpu_to_le16(Operation), }; memcpy(&PIMABlock.Params, Params, sizeof(uint32_t) * TotalParams); if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError) return ErrorCode; return PIPE_RWSTREAM_NoError; }