Send TCP or UDP packets from efi application - uefi
I want to develop an application to be automatically executed from startup.nsh in EFI shell. This application should send raw bytes to an ip address and receive some back. I looked everywhere for explanation and example for the implementation of simple network protocol in my code but found nothin. Can someone explain and show a code example using gnu_efi libaries?
Here is a sample how to send and receive UDP packets with EDK2, porting it to gnu-efi should be an easy task, wrap all gBS->, gRT-> and protocolXY calls with the uefi_call_wrapper.
Change the global values to match your client and server.
#include <Uefi.h>
#include <Library\UefiLib.h>
#include <Protocol\ServiceBinding.h>
#include <Protocol\Udp4.h>
#include <Protocol\SimpleNetwork.h>
#include <Protocol\ManagedNetwork.h>
#include <Protocol\Ip4.h>
#ifndef LOG
#define LOG(fmt, ...) AsciiPrint(fmt, __VA_ARGS__)
#endif
#ifndef TRACE
#define TRACE(status) LOG("Status: '%r', Function: '%a', File: '%a', Line: '%d'\r\n", status, __FUNCTION__, __FILE__, __LINE__)
#endif
static EFI_GUID gEfiUdp4ServiceBindingProtocolGuid = EFI_UDP4_SERVICE_BINDING_PROTOCOL_GUID;
static EFI_GUID gEfiUdp4ProtocolGuid = EFI_UDP4_PROTOCOL_GUID;
extern EFI_BOOT_SERVICES *gBS;
extern EFI_RUNTIME_SERVICES *gRT;
static BOOLEAN gTransmitCompleteFlag = FALSE;
static BOOLEAN gReceiveCompleteFlag = FALSE;
/*
Configuration
*/
static EFI_IPv4_ADDRESS gLocalAddress = { 10, 0, 2, 200 };
static EFI_IPv4_ADDRESS gSubnetMask = { 255, 255, 255, 0 };
static UINT16 gLocalPort = 0;
static EFI_IPv4_ADDRESS gRemoteAddress = { 10, 0, 2, 180 };
static UINT16 gRemotePort = 4444;
static VOID
EFIAPI
TransmitEventCallback(
IN EFI_EVENT Event,
IN void *UserData)
{
gTransmitCompleteFlag = TRUE;
}
static VOID
EFIAPI
ReceiveEventCallback(
IN EFI_EVENT Event,
IN void *UserData)
{
gReceiveCompleteFlag = TRUE;
}
static EFI_STATUS
EFIAPI
WaitForFlag(
IN BOOLEAN *Flag,
IN EFI_UDP4_PROTOCOL *Udp4Protocol OPTIONAL,
IN UINTN Timeout)
{
EFI_STATUS Status;
UINT8 LastSecond = MAX_UINT8;
UINT8 Timer = 0;
EFI_TIME CurrentTime;
while (!*Flag && (Timeout == 0 || Timer < Timeout)) {
if (Udp4Protocol) {
Udp4Protocol->Poll(
Udp4Protocol);
}
// use gRT->GetTime to exit this loop
Status = gRT->GetTime(&CurrentTime, NULL);
if (EFI_ERROR(Status)) {
TRACE(Status);
// Error handling
return Status;
}
if (LastSecond != CurrentTime.Second) {
LastSecond = CurrentTime.Second;
Timer++;
}
}
return *Flag ? EFI_SUCCESS : EFI_TIMEOUT;
}
EFI_STATUS
EFIAPI
UefiMain(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable)
{
EFI_STATUS Status;
EFI_UDP4_CONFIG_DATA Udp4ConfigData;
EFI_UDP4_COMPLETION_TOKEN Udp4ReceiveCompletionToken;
EFI_UDP4_COMPLETION_TOKEN Udp4TansmitCompletionToken;
EFI_UDP4_TRANSMIT_DATA Udp4TransmitData;
EFI_HANDLE Udp4ChildHandle = NULL;
EFI_UDP4_PROTOCOL *Udp4Protocol = NULL;
EFI_SERVICE_BINDING_PROTOCOL *Udp4ServiceBindingProtocol = NULL;
CHAR8 TxBuffer[] = "Hello Server!";
/*
Step 1: Locate the corresponding Service Binding Protocol, if there is more then 1 network interface gBS->LocateHandleBuffer should be used
*/
Status = gBS->LocateProtocol(
&gEfiUdp4ServiceBindingProtocolGuid,
NULL,
&Udp4ServiceBindingProtocol);
if (EFI_ERROR(Status)) {
TRACE(Status);
// Error handling
return Status;
}
/*
Step 2: Create a new UDP4 instance
*/
Status = Udp4ServiceBindingProtocol->CreateChild(
Udp4ServiceBindingProtocol,
&Udp4ChildHandle);
if (EFI_ERROR(Status)) {
TRACE(Status);
// Error handling
return Status;
}
Status = gBS->HandleProtocol(
Udp4ChildHandle,
&gEfiUdp4ProtocolGuid,
&Udp4Protocol);
if (EFI_ERROR(Status)) {
TRACE(Status);
// Error handling
return Status;
}
/*
Step 3: Prepare the UDP4 instance
*/
Udp4ConfigData.AcceptBroadcast = FALSE;
Udp4ConfigData.AcceptPromiscuous = FALSE;
Udp4ConfigData.AcceptAnyPort = FALSE;
Udp4ConfigData.AllowDuplicatePort = FALSE;
Udp4ConfigData.TimeToLive = 16;
Udp4ConfigData.TypeOfService = 0;
Udp4ConfigData.DoNotFragment = TRUE;
Udp4ConfigData.ReceiveTimeout = 0;
Udp4ConfigData.TransmitTimeout = 0;
// Change to TRUE and set the following fields to zero if DHCP is used
Udp4ConfigData.UseDefaultAddress = FALSE;
gBS->CopyMem(&Udp4ConfigData.StationAddress, &gLocalAddress, sizeof(Udp4ConfigData.StationAddress));
gBS->CopyMem(&Udp4ConfigData.SubnetMask, &gSubnetMask, sizeof(Udp4ConfigData.SubnetMask));
Udp4ConfigData.StationPort = gLocalPort;
gBS->CopyMem(&Udp4ConfigData.RemoteAddress, &gRemoteAddress, sizeof(Udp4ConfigData.RemoteAddress));
Udp4ConfigData.RemotePort = gRemotePort;
Status = Udp4Protocol->Configure(
Udp4Protocol,
&Udp4ConfigData);
if (EFI_ERROR(Status)) {
TRACE(Status);
// Error handling
return Status;
}
/*
Step 4: Send data and wait for completion
*/
Udp4TansmitCompletionToken.Status = EFI_SUCCESS;
Udp4TansmitCompletionToken.Event = NULL;
Status = gBS->CreateEvent(
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
TransmitEventCallback,
NULL,
&(Udp4TansmitCompletionToken.Event));
if (EFI_ERROR(Status)) {
TRACE(Status);
// Error handling
return Status;
}
Udp4TansmitCompletionToken.Packet.TxData = &Udp4TransmitData;
Udp4TransmitData.UdpSessionData = NULL;
gBS->SetMem(&Udp4TransmitData.GatewayAddress, sizeof(Udp4TransmitData.GatewayAddress), 0x00);
Udp4TransmitData.DataLength = sizeof(TxBuffer);
Udp4TransmitData.FragmentCount = 1;
Udp4TransmitData.FragmentTable[0].FragmentLength = Udp4TransmitData.DataLength;
Udp4TransmitData.FragmentTable[0].FragmentBuffer = TxBuffer;
gTransmitCompleteFlag = FALSE;
LOG("Sending data...\r\n");
Status = Udp4Protocol->Transmit(
Udp4Protocol,
&Udp4TansmitCompletionToken);
if (EFI_ERROR(Status)) {
TRACE(Status);
// Error handling
return Status;
}
Status = WaitForFlag(
&gTransmitCompleteFlag,
Udp4Protocol,
10);
if (EFI_ERROR(Status)) {
TRACE(EFI_TIMEOUT);
// Error handling
return EFI_TIMEOUT;
}
if (EFI_ERROR(Udp4TansmitCompletionToken.Status)) {
TRACE(Status);
// Error handling
return Status;
}
LOG("Data sent.\r\n");
/*
Step 5: Receive data
*/
Udp4ReceiveCompletionToken.Status = EFI_SUCCESS;
Udp4ReceiveCompletionToken.Event = NULL;
Status = gBS->CreateEvent(
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
ReceiveEventCallback,
NULL,
&(Udp4ReceiveCompletionToken.Event));
if (EFI_ERROR(Status)) {
TRACE(Status);
// Error handling
return Status;
}
Udp4ReceiveCompletionToken.Packet.RxData = NULL;
gReceiveCompleteFlag = FALSE;
LOG("Receiving data...\r\n");
Status = Udp4Protocol->Receive(
Udp4Protocol,
&Udp4ReceiveCompletionToken);
if (EFI_ERROR(Status)) {
TRACE(Status);
// Error handling
return Status;
}
Status = WaitForFlag(
&gReceiveCompleteFlag,
Udp4Protocol,
10);
if (EFI_ERROR(Status)) {
TRACE(EFI_TIMEOUT);
// Error handling
return EFI_TIMEOUT;
}
if (EFI_ERROR(Udp4ReceiveCompletionToken.Status)) {
TRACE(Status);
// Error handling
return Status;
}
/*
Step 6: Process received data
*/
if (
Udp4ReceiveCompletionToken.Packet.RxData &&
Udp4ReceiveCompletionToken.Packet.RxData->FragmentCount > 0 &&
Udp4ReceiveCompletionToken.Packet.RxData->DataLength > 0) {
LOG("Received '%a'.\r\n",
Udp4ReceiveCompletionToken.Packet.RxData->FragmentTable[0].FragmentBuffer);
}
else {
LOG("Received an empty package.\r\n");
}
/*
Step 7: Cleanup
*/
if (
Udp4ReceiveCompletionToken.Packet.RxData &&
Udp4ReceiveCompletionToken.Packet.RxData->RecycleSignal) {
Status = gBS->SignalEvent(Udp4ReceiveCompletionToken.Packet.RxData->RecycleSignal);
if (EFI_ERROR(Udp4ReceiveCompletionToken.Status)) {
TRACE(Status);
// Error handling
return Status;
}
}
Status = Udp4ServiceBindingProtocol->DestroyChild(
Udp4ServiceBindingProtocol,
Udp4ChildHandle);
if (EFI_ERROR(Udp4ReceiveCompletionToken.Status)) {
TRACE(Status);
// Error handling
return Status;
}
return EFI_SUCCESS;
}
Related
How to define a static private method outside the class in c++
#include <iostream> class BST { private: struct Bst_node { int data; struct Bst_node* left; struct Bst_node* right; }*root; // static Bst_node* get_inorder_predecessor(Bst_node* ptr); static BST::Bst_node* get_inorder_predecessor(Bst_node* ptr) { ptr = ptr->left; if (ptr == NULL) return NULL; while (ptr->right != NULL) { ptr = ptr->right; } return ptr; } public: void create() { root = new Bst_node; root->data = 8; root->right = NULL; root->left = new Bst_node; root->left->data = 10; root->left->left = NULL; root->left->right = NULL; } void print() { Bst_node * ptr = get_inorder_predecessor(this->root); if(ptr == NULL) std::cout<<"NULL\n"; else std::cout<<ptr->data<<std::endl; } }; int main() { BST obj; obj.create(); obj.print(); return 0; } The above code is working fine but when i define 'get_inorder_predecessor()' function outside the class it gives error see the below code. #include <iostream> class BST { private: struct Bst_node { int data; struct Bst_node* left; struct Bst_node* right; }*root; static Bst_node* get_inorder_predecessor(Bst_node* ptr); public: void create() {` root = new Bst_node; root->data = 8; root->right = NULL; root->left = new Bst_node; root->left->data = 10; root->left->left = NULL; root->left->right = NULL; } void print() { Bst_node * ptr = get_inorder_predecessor(this->root); if(ptr == NULL) std::cout<<"NULL\n"; else std::cout<<ptr->data<<std::endl; } }; static BST::Bst_node* get_inorder_predecessor(Bst_node* ptr) { ptr = ptr->left; if (ptr == NULL) return NULL; while (ptr->right != NULL) { ptr = ptr->right; } return ptr; } int main() { BST obj; obj.create(); obj.print(); return 0; } See the ERRORS: '''binary.cpp:33:13: error: 'struct BST::Bst_node' is private within this context static BST::Bst_node* get_inorder_predecessor(Bst_node* ptr) ^~~~~~~~ binary.cpp:4:12: note: declared private here struct Bst_node ^~~~~~~~ binary.cpp:33:47: error: 'Bst_node' was not declared in this scope static BST::Bst_node* get_inorder_predecessor(Bst_node* ptr) ^~~~~~~~ binary.cpp:33:57: error: 'ptr' was not declared in this scope static BST::Bst_node* get_inorder_predecessor(Bst_node* ptr) ^~~ '''
QueuUserAPC sometimes doesn't launc an apc routine in a thread waiting with GetQueuedCompletionStatusEx
I'm working on a simple async socket client built on top of winsock with io completion ports it sometimes works and sometimes blocks with strange behaviours this is the design of the async process : there are global iocp threads running to receive the completion packets and notify submitters the submitters use QueueUserApc routine to make the io call in the context of one of the waiting thread the apc routine makes the async io call and the the a waiter thread should receive the result and notify the issuer this is my simple wrapper for the io completion ports template <class T, auto CloseFn> struct HandleDeleter { using pointer = T; void operator ()(pointer handle) { CloseFn(handle); } }; using Handle = std::unique_ptr<void, HandleDeleter<HANDLE, CloseHandle>>; struct IoContext : public OVERLAPPED { IoContext() { memset(this, 0, sizeof(OVERLAPPED)); } }; struct CompletionResult { CompletionResult() : BytesTransferred(0), Key(0), Ctx(nullptr) {} CompletionResult(unsigned long bytes, uintptr_t key, IoContext* ctx) : BytesTransferred(bytes), Key(key), Ctx(ctx) {} unsigned long BytesTransferred; uintptr_t Key; IoContext *Ctx; }; class IoPort { Handle port_handle; public: IoPort() {} IoPort(Handle&& port) : port_handle(std::move(port)) {} IoPort(IoPort&& rhs) : port_handle(std::move(rhs.port_handle)) {} IoPort& operator=(IoPort&& rhs) { port_handle = std::move(rhs.port_handle); return *this; } bool Create(unsigned int max_threads = 0); bool AddToPort(Handle& file, uintptr_t key); bool AddToPort(SOCKET sock, uintptr_t key); bool GetResultOrApc(CompletionResult& result, DWORD WaitTimeMs); void Close() { port_handle.reset(); } }; bool IoPort::Create(unsigned int max_threads) { port_handle.reset(CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, max_threads)); return bool(port_handle); } bool IoPort::AddToPort(Handle & file, uintptr_t key) { return CreateIoCompletionPort(file.get(), port_handle.get(), key, 0) != nullptr; } bool IoPort::AddToPort(SOCKET sock, uintptr_t key) { return CreateIoCompletionPort((HANDLE)sock, port_handle.get(), key, 0) != nullptr; } bool IoPort::GetResultOrApc(CompletionResult & result, DWORD WaitTimeMs) { OVERLAPPED_ENTRY entry = { 0 }; DWORD count = 0; BOOL wait_result = GetQueuedCompletionStatusEx(port_handle.get(), &entry, 1, &count, WaitTimeMs, TRUE); if (entry.lpOverlapped) { result.Key = entry.lpCompletionKey; result.BytesTransferred = entry.dwNumberOfBytesTransferred; result.Ctx = (IoContext*)entry.lpOverlapped; } return wait_result; } then this is the global iocp threads that starts before entering main function struct IOCPThreads { iocp::IoPort Port; std::vector<std::thread> IoThreads; bool Exit = false; IOCPThreads() { if (!Port.Create()) std::cout << "[!] failed to open the port , error : " << GetLastError() << std::endl; auto num = std::thread::hardware_concurrency(); IoThreads.reserve(num); std::stringstream thd_ids; thd_ids << "threads ids : { "; for (auto i : range(0u, num)) { IoThreads.emplace_back(std::thread(&IOCPThreads::IoThread, this)); thd_ids << IoThreads[i].get_id() << ", "; } auto str = thd_ids.str(); str.pop_back(); str.pop_back(); str += " }"; std::cout << str << std::endl; } ~IOCPThreads() { Exit = true; for (auto& thd : IoThreads) if (thd.joinable()) thd.join(); } void IoThread() { while (!Exit) { iocp::CompletionResult result; Port.GetResultOrApc(result, 10); if (GetLastError() == WAIT_IO_COMPLETION) std::cout << "[*] received an apc" << std::endl; // sometimes print and sometimes no if (!result.Ctx) continue; DWORD transeferred, Flags; std::unique_ptr<ClientIoCtx> ctx((ClientIoCtx*)result.Ctx); WSAGetOverlappedResult(ctx->sock->GetHandle().get(), ctx.get(), &transeferred, FALSE, &Flags); int WsaError = WSAGetLastError(); if (ctx->op == ClientIoOp::Recv) { std::unique_ptr<ClientIoRecvCtx> RecvCtx = unique_static_cast<ClientIoRecvCtx>(ctx); RecvCtx->OnResult(*RecvCtx->sock, WsaError, std::span{ RecvCtx->buffer, RecvCtx->buffer + RecvCtx->length }, transeferred); } } } }; IOCPThreads ClientIoThreads; and this is the socket implemention : enum class async_status_code : unsigned int { Pending, Finished, Error, }; struct AsyncResult { async_status_code code; unsigned int transferred; AsyncResult() : code(async_status_code::Error), transferred(0) {} AsyncResult(async_status_code c, unsigned int s) : code(c), transferred(s) {} bool IsPending() const { return code == async_status_code::Pending; } bool IsFinished() const { return code == async_status_code::Finished; } bool IsFailed() const { return code == async_status_code::Error; } }; using AsyncSendFunc = std::function<void(Socket& sock, int ErrorCode, std::span<const char> Buffer, DWORD transeferred)>; enum class SendRecvFlags { UnSpecefied = 0, MsgDontRoute = 0x4, MsgOOB = 0x1, MsgPeek = 0x2, MsgWaitAll = 0x8, MsgPushImmediate = 0x20, }; enum class ClientIoOp { Send, }; struct ApcResult { async_status_code code; DWORD transeferred; int error; }; struct ClientIoCtx : public IoContext { Socket *sock; ClientIoOp op; promise<ApcResult> notifier; }; struct ClientIoSendCtx : public ClientIoCtx { ClientIoSendCtx() { op = ClientIoOp::Send; } const char *buffer; int length; SendRecvFlags flags; AsyncSendFunc OnResult; }; AsyncResult LIB_NAMESPACE::net::Socket::AsyncSend(const char * buffer, int length, io::IoContext & IoCtx, SendRecvFlags flags) { WSABUF buff_vec{ length, (char*)buffer }; DWORD sent = 0; if (WSASend(sock.get(), &buff_vec, 1, &sent, (DWORD)flags, &IoCtx, nullptr) == 0) return AsyncResult(async_status_code::Finished, sent); else if (WSAGetLastError() == WSA_IO_PENDING) return AsyncResult(async_status_code::Pending, sent); return AsyncResult(); } AsyncResult LIB_NAMESPACE::net::Socket::AsyncSend(const char * buffer, int length, const AsyncSendFunc & OnSend, SendRecvFlags flags) { ClientIoSendCtx *ctx = new ClientIoSendCtx(); ctx->sock = this; ctx->buffer = buffer; ctx->length = length; ctx->flags = flags; ctx->OnResult = OnSend; auto fut = ctx->notifier.get_future(); // notifier is a promise auto& thd = ClientIoThreads.IoThreads[RandomUInt(0, ClientIoThreads.IoThreads.size() - 1)]; std::cout << "[*] launchin the apc routine in thread : " << thd.get_id() << std::endl; // it's always one of the io threads auto dwRes = QueueUserAPC(Socket::ApcRoutine, thd.native_handle(), (ULONG_PTR)ctx); if (!dwRes) // doesn't happen { delete ctx; std::cout << "QueueUserAPC failed with error " << GetLastError() << std::endl; return AsyncResult(); } auto result = fut.get(); // --> blocks here because the apc routine doesn't start WSASetLastError(result.error); // the wsa error is thread local so I transfer it from the apc thread to this thread return AsyncResult(result.code, result.transeferred); } void ApcRoutine(unsigned long long Param) { std::cout << "[*] ApcRoutine started" << std::endl; // sometimes is printed and sometimes no std::unique_ptr<ClientIoCtx> ctx((ClientIoCtx*)Param); if (ctx->op == ClientIoOp::Send) { std::unique_ptr<ClientIoSendCtx> SendCtx = unique_static_cast<ClientIoSendCtx>(ctx); auto async_result = SendCtx->sock->AsyncSend(SendCtx->buffer, SendCtx->length, *SendCtx, SendCtx->flags); ApcResult apc_result; apc_result.code = async_result.code; apc_result.transeferred = async_result.transferred; apc_result.error = WSAGetLastError(); SendCtx->notifier.set_value(apc_result); if (apc_result.code != async_status_code::Error) SendCtx.release(); } } the problem is that the QueuUserApc sometimes doesn't fail but the apc routine doesn't start so the the issuer thread blocks waiting with future::get I checked the GetLasError() value every time after calling QueuUserApc and it is always 0 so what is wrong here ?
JPEG streaming with live555
I want to stream JPEG images or motion-JPEG file through live 555. But the problem is that in live 555 implementation for Jpegs is not available. Anyone can help ??
You can find a implementation that was posted to the devel mailing list http://lists.live555.com/pipermail/live-devel/2012-February/014672.html. The code and a sample is available but this modification was rejected by live555 maintainer. First we need to implement an MJPEGVideoSource than can feed a JPEGVideoRTPSink. #include "JPEGVideoSource.hh" class MJPEGVideoSource : public JPEGVideoSource { public: static MJPEGVideoSource* createNew (UsageEnvironment& env, FramedSource* source) { return new MJPEGVideoSource(env,source); } virtual void doGetNextFrame() { if (m_inputSource) m_inputSource->getNextFrame(fTo, fMaxSize, afterGettingFrameSub, this, FramedSource::handleClosure, this); } virtual void doStopGettingFrames() { FramedSource::doStopGettingFrames(); if (m_inputSource) m_inputSource->stopGettingFrames(); } static void afterGettingFrameSub(void* clientData, unsigned frameSize,unsigned numTruncatedBytes,struct timeval presentationTime,unsigned durationInMicroseconds) { MJPEGVideoSource* source = (MJPEGVideoSource*)clientData; source->afterGettingFrame(frameSize, numTruncatedBytes, presentationTime, durationInMicroseconds); } void afterGettingFrame(unsigned frameSize,unsigned numTruncatedBytes,struct timeval presentationTime,unsigned durationInMicroseconds) { int headerSize = 0; bool headerOk = false; fFrameSize = 0; for (unsigned int i = 0; i < frameSize ; ++i) { // SOF if ( (i+8) < frameSize && fTo[i] == 0xFF && fTo[i+1] == 0xC0 ) { m_height = (fTo[i+5]<<5)|(fTo[i+6]>>3); m_width = (fTo[i+7]<<5)|(fTo[i+8]>>3); } // DQT if ( (i+5+64) < frameSize && fTo[i] == 0xFF && fTo[i+1] == 0xDB) { if (fTo[i+4] ==0) { memcpy(m_qTable, fTo + i + 5, 64); m_qTable0Init = true; } else if (fTo[i+4] ==1) { memcpy(m_qTable + 64, fTo + i + 5, 64); m_qTable1Init = true; } } // End of header if ( (i+1) < frameSize && fTo[i] == 0x3F && fTo[i+1] == 0x00 ) { headerOk = true; headerSize = i+2; break; } } if (headerOk) { fFrameSize = frameSize - headerSize; memmove( fTo, fTo + headerSize, fFrameSize ); } fNumTruncatedBytes = numTruncatedBytes; fPresentationTime = presentationTime; fDurationInMicroseconds = durationInMicroseconds; afterGetting(this); } virtual u_int8_t type() { return 1; }; virtual u_int8_t qFactor() { return 128; }; virtual u_int8_t width() { return m_width; }; virtual u_int8_t height() { return m_height; }; u_int8_t const* quantizationTables( u_int8_t& precision, u_int16_t& length ) { length = 0; precision = 0; if ( m_qTable0Init && m_qTable1Init ) { precision = 8; length = sizeof(m_qTable); } return m_qTable; } protected: MJPEGVideoSource(UsageEnvironment& env, FramedSource* source) : JPEGVideoSource(env), m_inputSource(source), m_width(0), m_height(0), m_qTable0Init(false), m_qTable1Init(false) { memset(&m_qTable,0,sizeof(m_qTable)); } virtual ~MJPEGVideoSource() { Medium::close(m_inputSource); } protected: FramedSource* m_inputSource; u_int8_t m_width; u_int8_t m_height; u_int8_t m_qTable[128]; bool m_qTable0Init; bool m_qTable1Init; }; Next we can use it as a video source in order to build a simple RTSP server: #include "liveMedia.hh" #include "BasicUsageEnvironment.hh" #include "GroupsockHelper.hh" #include "MJPEGVideoSource.hh" char const* inputFileName = "test.mjpeg"; int main(int argc, char** argv) { // Begin by setting up our usage environment: TaskScheduler* scheduler = BasicTaskScheduler::createNew(); UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler); // Create 'groupsocks' for RTP and RTCP: struct in_addr destinationAddress; destinationAddress.s_addr = chooseRandomIPv4SSMAddress(*env); const unsigned short rtpPortNum = 18888; const unsigned short rtcpPortNum = rtpPortNum+1; const unsigned char ttl = 255; const Port rtpPort(rtpPortNum); const Port rtcpPort(rtcpPortNum); Groupsock rtpGroupsock(*env, destinationAddress, rtpPort, ttl); rtpGroupsock.multicastSendOnly(); // we're a SSM source Groupsock rtcpGroupsock(*env, destinationAddress, rtcpPort, ttl); rtcpGroupsock.multicastSendOnly(); // we're a SSM source // Create a 'JPEG Video RTP' sink from the RTP 'groupsock': RTPSink* videoSink = JPEGVideoRTPSink::createNew(*env, &rtpGroupsock); // Create (and start) a 'RTCP instance' for this RTP sink: const unsigned estimatedSessionBandwidth = 5000; // in kbps; for RTCP b/w share const unsigned maxCNAMElen = 100; unsigned char CNAME[maxCNAMElen+1]; gethostname((char*)CNAME, maxCNAMElen); CNAME[maxCNAMElen] = '\0'; // just in case RTCPInstance* rtcp = RTCPInstance::createNew(*env, &rtcpGroupsock, estimatedSessionBandwidth, CNAME, videoSink, NULL /* we're a server */, True /* we're a SSM source */); // Note: This starts RTCP running automatically RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554); if (rtspServer == NULL) { *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n"; exit(1); } ServerMediaSession* sms = ServerMediaSession::createNew(*env, "testStream", inputFileName,"Session streamed by \"testMJPEGVideoStreamer\"", True /*SSM*/); sms->addSubsession(PassiveServerMediaSubsession::createNew(*videoSink, rtcp)); rtspServer->addServerMediaSession(sms); char* url = rtspServer->rtspURL(sms); *env << "Play this stream using the URL \"" << url << "\"\n"; delete[] url; // Start the streaming: *env << "Beginning streaming...\n"; // Open the input file as a 'byte-stream file source': ByteStreamFileSource* fileSource = ByteStreamFileSource::createNew(*env, inputFileName); if (fileSource == NULL) { *env << "Unable to open file \"" << inputFileName << "\" as a byte-stream file source\n"; exit(1); } // Create the MJPEG video source: MJPEGVideoSource* videoSource = MJPEGVideoSource::createNew(*env, fileSource); // Finally, start playing: *env << "Beginning to read from file...\n"; videoSink->startPlaying(*videoSource, NULL, NULL); env->taskScheduler().doEventLoop(); return 0; }
Hope you have done it but if not- see this Jpeg Streaming using live555 This is doing the same thing as you have asked to stream the images/Jpegs. For MJpegs you'll have to do the same process.
Linux SPI driver crasj
I am trying to write a SPI driver for Angstrom Linux 2.6.36 for Gumstix Overo Fire. My driver keeps on crashing in the interrupt handler. Here is the full code #include <linux/init.h> #include <linux/module.h> #include <linux/ioctl.h> #include <linux/fs.h> #include <linux/device.h> #include <linux/err.h> #include <linux/errno.h> #include <linux/mutex.h> #include <linux/slab.h> #include <linux/smp_lock.h> #include <linux/cdev.h> #include <linux/spi/spi.h> #include <linux/string.h> #include <asm/uaccess.h> #include <linux/kernel.h> #include <mach/gpio.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/kthread.h> #include <linux/hrtimer.h> #define IRQ_PIN 10 #define SPI_BUFF_SIZE 4 #define USER_BUFF_SIZE 128 #define SPI_BUS 1 #define SPI_BUS_CS1 1 #define SPI_BUS_SPEED 1500000 unsigned char *buff_even = 0; unsigned char *buff_odd = 0; unsigned char *temp_buff = 0; unsigned int sample_counter = 0; unsigned int buff_counter = 0; unsigned int current_buffer = 0; unsigned int local_current_buffer = 0; unsigned int local_sample_counter = 0; unsigned int num_reads = 0; unsigned int num_miss_samples = 0; unsigned int regval = 0; #define LIMIT (4000) #define BUFF_SIZE (4*LIMIT) #define MAJOR_NUM 100 #define READ_CURR_COUNTER _IOWR(MAJOR_NUM, 1, int) #define READ_BUFF _IOWR(MAJOR_NUM, 2, int) #define READ_CURR_BUFF_NO _IOWR(MAJOR_NUM, 3, int) #define READ_REGISTER _IOWR(MAJOR_NUM, 4, unsigned char) #define WRITE_REGISTER _IOWR(MAJOR_NUM, 5, int) #define START_READ _IOWR(MAJOR_NUM, 6, int) #define STOP_READ _IOWR(MAJOR_NUM, 7, int) const char this_driver_name[] = "adc"; static int running = 0; static int resetting = 0; static int reading = 0; struct spike_control { struct spi_message msg; struct spi_transfer transfer; u8 *tx_buff; u8 *rx_buff; }; static struct spike_control spike_ctl; struct spike_dev { struct semaphore spi_sem; struct semaphore fop_sem; dev_t devt; struct cdev cdev; struct class *class; struct spi_device *spi_device; char *user_buff; u8 test_data; int irq; }; static struct spike_dev spike_dev; static DEFINE_MUTEX(list_lock); static DEFINE_MUTEX(count_lock); static int status; static void spike_completion_handler(void *arg) { local_sample_counter++; if (sample_counter >= local_sample_counter + 1) num_miss_samples++; if (current_buffer == 0) { buff_even[buff_counter++] = spike_ctl.rx_buff[0]; buff_even[buff_counter++] = spike_ctl.rx_buff[1]; buff_even[buff_counter++] = spike_ctl.rx_buff[2]; buff_even[buff_counter++] = spike_ctl.rx_buff[3]; } else if (current_buffer == 1) { buff_odd[buff_counter++] = spike_ctl.rx_buff[0]; buff_odd[buff_counter++] = spike_ctl.rx_buff[1]; buff_odd[buff_counter++] = spike_ctl.rx_buff[2]; buff_odd[buff_counter++] = spike_ctl.rx_buff[3]; } memset(spike_ctl.rx_buff, 0, SPI_BUFF_SIZE); if (sample_counter == LIMIT) { buff_counter = 0; mutex_lock(&count_lock); if (current_buffer == 0) current_buffer = 1; else current_buffer = 0; sample_counter = 0; mutex_unlock(&count_lock); local_sample_counter = 0; } } static irqreturn_t adc_handler(int irq, void *dev_id) { sample_counter++; spi_message_init(&spike_ctl.msg); spike_ctl.msg.complete = spike_completion_handler; spike_ctl.msg.context = NULL; spike_ctl.transfer.tx_buf = NULL; spike_ctl.transfer.rx_buf = spike_ctl.rx_buff; spike_ctl.transfer.len = 4; spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); status = spi_async(spike_dev.spi_device, &spike_ctl.msg); return IRQ_HANDLED; } static void resetbuffers(void) { local_sample_counter = 0; sample_counter = 0; num_miss_samples = 0; current_buffer = 0; buff_counter = 0; memset(spike_ctl.rx_buff, 0, SPI_BUFF_SIZE); memset(spike_ctl.tx_buff, 0, SPI_BUFF_SIZE); memset(buff_even, 0, BUFF_SIZE); memset(buff_odd, 0, BUFF_SIZE); memset(temp_buff, 0, BUFF_SIZE); } static int read_register(unsigned char addr) { if (down_interruptible(&spike_dev.spi_sem)) return -ERESTARTSYS; if (!spike_dev.spi_device) { up(&spike_dev.spi_sem); return -ENODEV; } memset(spike_ctl.rx_buff, 0, SPI_BUFF_SIZE); memset(spike_ctl.tx_buff, 0, SPI_BUFF_SIZE); spike_ctl.transfer.tx_buf = spike_ctl.tx_buff; spike_ctl.transfer.rx_buf = spike_ctl.rx_buff; spike_ctl.transfer.len = 1; spike_ctl.tx_buff[0] = 0x11;//Stop read data continuous spi_message_init(&spike_ctl.msg); spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); __asm__ __volatile__("ldr r0,=0x2710\n\t" ".LOOP1:\n\t" "subs r0,r0,#1\n\t" "bne .LOOP1\n\t"); spike_ctl.tx_buff[0] = 0x20 + addr;//Address of register spi_message_init(&spike_ctl.msg); spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); __asm__ __volatile__("ldr r0,=0x2710\n\t" ".LOOP2:\n\t" "subs r0,r0,#1\n\t" "bne .LOOP2\n\t"); spike_ctl.tx_buff[0] = 0;//Number of registers to read minus 1 spi_message_init(&spike_ctl.msg); spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); __asm__ __volatile__("ldr r0,=0x2710\n\t" ".LOOP3:\n\t" "subs r0,r0,#1\n\t" "bne .LOOP3\n\t"); spi_message_init(&spike_ctl.msg); spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); __asm__ __volatile__("ldr r0,=0x2710\n\t" ".LOOP4:\n\t" "subs r0,r0,#1\n\t" "bne .LOOP4\n\t"); printk(KERN_ALERT "%x\n",spike_ctl.rx_buff[0]); regval = spike_ctl.rx_buff[0]; // spike_ctl.tx_buff[0] = 0x10;//Start read data continuous // spi_message_init(&spike_ctl.msg); // spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); // status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); up(&spike_dev.spi_sem); return status; } static int write_register(unsigned char addr, unsigned char val) { if (down_interruptible(&spike_dev.spi_sem)) return -ERESTARTSYS; if (!spike_dev.spi_device) { up(&spike_dev.spi_sem); return -ENODEV; } memset(spike_ctl.rx_buff, 0, SPI_BUFF_SIZE); memset(spike_ctl.tx_buff, 0, SPI_BUFF_SIZE); spike_ctl.transfer.tx_buf = spike_ctl.tx_buff; spike_ctl.transfer.rx_buf = spike_ctl.rx_buff; spike_ctl.transfer.len = 1; spike_ctl.tx_buff[0] = 0x11;//Stop read data continuous spi_message_init(&spike_ctl.msg); spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); __asm__ __volatile__("ldr r0,=0x2710\n\t" ".LOOP5:\n\t" "subs r0,r0,#1\n\t" "bne .LOOP5\n\t"); spike_ctl.tx_buff[0] = 0x40 + addr;//Address of register spi_message_init(&spike_ctl.msg); spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); __asm__ __volatile__("ldr r0,=0x2710\n\t" ".LOOP6:\n\t" "subs r0,r0,#1\n\t" "bne .LOOP6\n\t"); spike_ctl.tx_buff[0] = 0;//Number of registers to read minus 1 spi_message_init(&spike_ctl.msg); spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); __asm__ __volatile__("ldr r0,=0x2710\n\t" ".LOOP7:\n\t" "subs r0,r0,#1\n\t" "bne .LOOP7\n\t"); spike_ctl.tx_buff[0] = val;//Value to write spi_message_init(&spike_ctl.msg); spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); __asm__ __volatile__("ldr r0,=0x2710\n\t" ".LOOP8:\n\t" "subs r0,r0,#1\n\t" "bne .LOOP8\n\t"); spike_ctl.tx_buff[0] = 0x10;//Start read data continuous spi_message_init(&spike_ctl.msg); spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); // spike_ctl.tx_buff[0] = 0x10;//Start read data continuous // spi_message_init(&spike_ctl.msg); // spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); // status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); up(&spike_dev.spi_sem); return status; } static long adc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { unsigned char addr; switch(cmd) { case READ_CURR_COUNTER: mutex_lock(&count_lock); local_current_buffer = current_buffer; local_sample_counter = sample_counter; mutex_unlock(&count_lock); copy_to_user((void *)arg, &local_sample_counter, sizeof(unsigned int)); printk(KERN_ALERT "Read current counter %d\n",local_sample_counter); break; case READ_BUFF: mutex_lock(&count_lock); local_current_buffer = current_buffer; local_sample_counter = sample_counter; mutex_unlock(&count_lock); if (local_current_buffer == 0) { memcpy(temp_buff,buff_odd, BUFF_SIZE); // memset(temp_buff, 'Q', BUFF_SIZE); } else { memcpy(temp_buff,buff_even, BUFF_SIZE); // memset(temp_buff, 'T', BUFF_SIZE); } copy_to_user((void *)arg, temp_buff, BUFF_SIZE); num_reads++; break; case READ_CURR_BUFF_NO: mutex_lock(&count_lock); local_current_buffer = current_buffer; local_sample_counter = sample_counter; mutex_unlock(&count_lock); copy_to_user((void *)arg, &local_current_buffer, sizeof(int)); break; case READ_REGISTER: get_user(addr, (unsigned char *)arg); disable_irq(spike_dev.irq); read_register(addr); enable_irq(spike_dev.irq); copy_to_user((void *)arg, ®val, sizeof(int)); break; case WRITE_REGISTER: disable_irq(spike_dev.irq); enable_irq(spike_dev.irq); //copy_to_user((void *)arg, &local_current_buffer, sizeof(int)); break; default: return -ENOTTY; } return 1; } static int spike_open(struct inode *inode, struct file *filp) { int status = 0; if (down_interruptible(&spike_dev.fop_sem)) return -ERESTARTSYS; if (!spike_dev.user_buff) { spike_dev.user_buff = kmalloc(USER_BUFF_SIZE, GFP_KERNEL); if (!spike_dev.user_buff) status = -ENOMEM; } up(&spike_dev.fop_sem); return status; } static int spike_probe(struct spi_device *spi_device) { if (down_interruptible(&spike_dev.spi_sem)) return -EBUSY; spike_dev.spi_device = spi_device; printk(KERN_ALERT "SPI[%d] max_speed_hz %d Hz\n", spi_device->chip_select, spi_device->max_speed_hz); up(&spike_dev.spi_sem); return 0; } static int spike_remove(struct spi_device *spi_device) { if (down_interruptible(&spike_dev.spi_sem)) return -EBUSY; spike_dev.spi_device = NULL; up(&spike_dev.spi_sem); return 0; } static int __init add_spike_device_to_bus(void) { struct spi_master *spi_master; struct spi_device *spi_device; struct device *pdev; char buff[64]; int status = 0; spi_master = spi_busnum_to_master(SPI_BUS); if (!spi_master) { printk(KERN_ALERT "spi_busnum_to_master(%d) returned NULL\n", SPI_BUS); printk(KERN_ALERT "Missing modprobe omap2_mcspi?\n"); return -1; } spi_device = spi_alloc_device(spi_master); if (!spi_device) { put_device(&spi_master->dev); printk(KERN_ALERT "spi_alloc_device() failed\n"); return -1; } spi_device->chip_select = SPI_BUS_CS1; /* Check whether this SPI bus.cs is already claimed */ snprintf(buff, sizeof(buff), "%s.%u", dev_name(&spi_device->master->dev), spi_device->chip_select); pdev = bus_find_device_by_name(spi_device->dev.bus, NULL, buff); if (pdev) { /* We are not going to use this spi_device, so free it */ spi_dev_put(spi_device); /* * There is already a device configured for this bus.cs * It is okay if it us, otherwise complain and fail. */ if (pdev->driver && pdev->driver->name && strcmp(this_driver_name, pdev->driver->name)) { printk(KERN_ALERT "Driver [%s] already registered for %s\n", pdev->driver->name, buff); status = -1; } } else { spi_device->max_speed_hz = SPI_BUS_SPEED; spi_device->mode = SPI_MODE_0; spi_device->bits_per_word = 8; spi_device->irq = -1; spi_device->controller_state = NULL; spi_device->controller_data = NULL; strlcpy(spi_device->modalias, this_driver_name, SPI_NAME_SIZE); status = spi_add_device(spi_device); if (status < 0) { spi_dev_put(spi_device); printk(KERN_ALERT "spi_add_device() failed: %d\n", status); } } put_device(&spi_master->dev); return status; } static struct spi_driver spike_driver = { .driver = { .name = this_driver_name, .owner = THIS_MODULE, }, .probe = spike_probe, .remove = __devexit_p(spike_remove), }; static int __init spike_init_spi(void) { int error; spike_ctl.tx_buff = kmalloc(SPI_BUFF_SIZE, GFP_KERNEL | GFP_DMA); if (!spike_ctl.tx_buff) { error = -ENOMEM; goto spike_init_error; } spike_ctl.rx_buff = kmalloc(SPI_BUFF_SIZE, GFP_KERNEL | GFP_DMA); if (!spike_ctl.rx_buff) { error = -ENOMEM; goto spike_init_error; } error = spi_register_driver(&spike_driver); if (error < 0) { printk(KERN_ALERT "spi_register_driver() failed %d\n", error); goto spike_init_error; } error = add_spike_device_to_bus(); if (error < 0) { printk(KERN_ALERT "add_spike_to_bus() failed\n"); spi_unregister_driver(&spike_driver); goto spike_init_error; } spike_dev.irq = OMAP_GPIO_IRQ(IRQ_PIN); return 0; spike_init_error: if (spike_ctl.tx_buff) { kfree(spike_ctl.tx_buff); spike_ctl.tx_buff = 0; } if (spike_ctl.rx_buff) { kfree(spike_ctl.rx_buff); spike_ctl.rx_buff = 0; } return error; } static ssize_t spike_read(struct file *filp, char __user *buff, size_t count, loff_t *offp) { size_t len; ssize_t status = 0; if (!buff) return -EFAULT; if (*offp > 0) return 0; if (down_interruptible(&spike_dev.fop_sem)) return -ERESTARTSYS; printk(KERN_ALERT "Interrupt triggered %d Missed packet %d\n", sample_counter, num_miss_samples); up(&spike_dev.fop_sem); return status; } static ssize_t spike_write(struct file *filp, const char __user *buff, size_t count, loff_t *f_pos) { size_t len; ssize_t status = 0; if (down_interruptible(&spike_dev.fop_sem)) return -ERESTARTSYS; memset(spike_dev.user_buff, 0, 16); len = count > 8 ? 8 : count; if (copy_from_user(spike_dev.user_buff, buff, len)) { status = -EFAULT; goto spike_write_done; } /* we'll act as if we looked at all the data */ status = count; /* but we only care about the first 5 characters */ if (!strnicmp(spike_dev.user_buff, "inc", 3)) { disable_irq(spike_dev.irq); write_register(1,0x62); resetbuffers(); printk(KERN_ALERT "4000 samples per second\n"); enable_irq(spike_dev.irq); } if (!strnicmp(spike_dev.user_buff, "dec", 3)) { disable_irq(spike_dev.irq); write_register(1,0x52); resetbuffers(); printk(KERN_ALERT "1000 samples per second\n"); enable_irq(spike_dev.irq); } if (!strnicmp(spike_dev.user_buff, "stop", 4)) { disable_irq(spike_dev.irq); resetbuffers(); printk(KERN_ALERT "Driver stopped\n"); } spike_write_done: up(&spike_dev.fop_sem); return status; } static const struct file_operations spike_fops = { .owner = THIS_MODULE, .open = spike_open, .read = spike_read, .write = spike_write, .unlocked_ioctl = adc_ioctl, }; static int __init spike_init_cdev(void) { int error; spike_dev.devt = MKDEV(0, 0); error = alloc_chrdev_region(&spike_dev.devt, 0, 1, this_driver_name); if (error < 0) { printk(KERN_ALERT "alloc_chrdev_region() failed: %d \n", error); return -1; } cdev_init(&spike_dev.cdev, &spike_fops); spike_dev.cdev.owner = THIS_MODULE; error = cdev_add(&spike_dev.cdev, spike_dev.devt, 1); if (error) { printk(KERN_ALERT "cdev_add() failed: %d\n", error); unregister_chrdev_region(spike_dev.devt, 1); return -1; } return 0; } static int __init spike_init_class(void) { spike_dev.class = class_create(THIS_MODULE, this_driver_name); if (!spike_dev.class) { printk(KERN_ALERT "class_create() failed\n"); return -1; } if (!device_create(spike_dev.class, NULL, spike_dev.devt, NULL, this_driver_name)) { printk(KERN_ALERT "device_create(..., %s) failed\n", this_driver_name); class_destroy(spike_dev.class); return -1; } return 0; } static int __init spike_init(void) { int result; memset(&spike_dev, 0, sizeof(spike_dev)); memset(&spike_ctl, 0, sizeof(spike_ctl)); sema_init(&spike_dev.spi_sem, 1); sema_init(&spike_dev.fop_sem, 1); buff_even = kmalloc(BUFF_SIZE, GFP_KERNEL); buff_odd = kmalloc(BUFF_SIZE, GFP_KERNEL); temp_buff = kmalloc(BUFF_SIZE, GFP_KERNEL); if ( buff_even == 0 ) printk(KERN_ALERT "Failed to allocate buffer even\n"); if ( buff_odd == 0 ) printk(KERN_ALERT "Failed to allocate buffer odd\n"); if ( temp_buff == 0 ) printk(KERN_ALERT "Failed to temp buffer\n"); if (spike_init_cdev() < 0) goto fail_1; if (spike_init_class() < 0) goto fail_2; if (spike_init_spi() < 0) goto fail_3; result = request_irq(spike_dev.irq, adc_handler, IRQF_TRIGGER_RISING, "adc", &spike_dev); if (result < 0) { printk(KERN_ALERT "request_irq failed: %d\n", result); return -1; } return 0; fail_3: device_destroy(spike_dev.class, spike_dev.devt); class_destroy(spike_dev.class); fail_2: cdev_del(&spike_dev.cdev); unregister_chrdev_region(spike_dev.devt, 1); fail_1: return -1; } module_init(spike_init); static void __exit spike_exit(void) { disable_irq(spike_dev.irq); free_irq(spike_dev.irq, &spike_dev); gpio_free(IRQ_PIN); spi_unregister_device(spike_dev.spi_device); spi_unregister_driver(&spike_driver); device_destroy(spike_dev.class, spike_dev.devt); class_destroy(spike_dev.class); cdev_del(&spike_dev.cdev); unregister_chrdev_region(spike_dev.devt, 1); if (spike_ctl.tx_buff) kfree(spike_ctl.tx_buff); if (spike_ctl.rx_buff) kfree(spike_ctl.rx_buff); if (spike_dev.user_buff) kfree(spike_dev.user_buff); if ( buff_even != 0 ) kfree(buff_even); if ( buff_odd != 0 ) kfree(buff_odd); if ( temp_buff != 0 ) kfree(temp_buff); printk(KERN_ALERT "Interrupt triggered %d Missed packet %d\n", sample_counter, num_miss_samples); } module_exit(spike_exit); The interrupt handler crashes on the line status = spi_async(spike_dev.spi_device, &spike_ctl.msg); If i comment out this line everything runs fine but of course no data is read from SPI.
Muhammad, maybe you solved this issue by the time. However, what I see is that you're using mutexes in the SPI completion handler (spike_completion_handler), which is executed in a context that cannot sleep. Therefore, I would advise to use spinlocks instead. This is safe to do, because count_lock always protects code that does not sleep. That may not be the cause of your problem (did not read the whole code), but it's still better to do it this way.
How to get the keycode for different mobiles using j2me
I am developing application for Nokia using Netbeans platform. Now I am in idea to make this application to work on any java enabled mobile. So for that I have to get the platform of the devices, how can I get it(specifically for micromax, blackberry) mobiles? Also the left and right softkey code.
I found one answer which is given this link. the KeyCodeAdapter class provided by above link is like below import javax.microedition.lcdui.Canvas; /** * Class redefines codes of mobile phone to our constant values. * Class can give to developers following information: * <ul> * <li/><i>defined platform name</i><br> * In case if device vendor not defined we'll recieve <code>PLATFORM_NOT_DEFINED</code> like platform name. * Same in this case keyCodes will be setted like for Nokia and SE. It's done for work on emulators, * because on some of them it's impossible to define platform name. * <li/><i>adopted to our constants key code value</i> * <li/><i>for test returns defined real code of left softkey</i> * </ul> */ public final class KeyCodeAdapter { /** * instance on this class */ private static final KeyCodeAdapter instance = new KeyCodeAdapter(); /** * canvas used for definig codes */ private final Canvas adaptorCanvas; /** * constants for platforms names */ public static final String PLATFORM_MOTOROLA = "motorola"; public static final String PLATFORM_NOKIA = "nokia"; public static final String PLATFORM_SONY_ERICSSON = "SE"; public static final String PLATFORM_SIEMENS = "siemens"; public static final String PLATFORM_SAMSUNG = "samsung"; public static final String PLATFORM_LG = "LG"; public static final String PLATFORM_NOT_DEFINED = "NA"; /** * constants for keycodes */ public static final int SOFT_KEY_LEFT = -201; public static final int SOFT_KEY_RIGHT = -202; public static final int SOFT_KEY_MIDDLE_INTERNET = -203; /** * this key is present on Nokia s60 */ public static final int PENCIL_KEY = -207; public static final int DELETE_KEY = -204; public static final int BACK_KEY = -205; // public static final int SEND_KEY = -206; //constant will be used in future for green key start dialling public static final int KEY_1 = 201; public static final int KEY_2 = 202; public static final int KEY_3 = 203; public static final int KEY_4 = 204; public static final int KEY_5 = 205; public static final int KEY_6 = 206; public static final int KEY_7 = 207; public static final int KEY_8 = 208; public static final int KEY_9 = 209; public static final int KEY_0 = 200; public static final int KEY__POUND = 211; public static final int KEY__STAR = 212; /** * KEYS on JOISTICK */ public static final int UP_KEY = 221; public static final int DOWN_KEY = 222; public static final int LEFT_KEY = 223; public static final int RIGHT_KEY = 224; public static final int CENTER_KEY = 225; public static final int NOT_DEFINED_KEY = 254; /** * current platform name */ private final String PLATFORM_NAME; /** * current platform codeofSoftkey */ private final int SOFTKEY_LEFT; private final int SOFTKEY_RIGHT; private final int SOFTKEY_MIDDLE_INTERNET; private final int SOFTKEY_DELETE; private final int SOFTKEY_BACK; /** * standart values for softkeys of different platforms * used only in predefining */ private static final int SOFT_KEY_LEFT_SE = -6; private static final int SOFT_KEY_RIGHT_SE = -7; private static final int DELETE_KEY_SE = -8; private static final int INTERNET_KEY_SE = -10; private static final int BACK_KEY_SE = -11; private static final int SOFT_KEY_LEFT_SAMSUNG = -6; private static final int SOFT_KEY_RIGHT_SAMSUNG = -7; private static final int DELETE_KEY_SAMSUNG = -8; private static final int SOFT_KEY_LEFT_SIEMENS = -1; private static final int SOFT_KEY_RIGHT_SIEMENS = -4; private static final int SOFT_KEY_LEFT_NOKIA = -6; private static final int SOFT_KEY_RIGHT_NOKIA = -7; private static final int DELETE_KEY_NOKIA = -8; private static final int PENCIL_KEY_NOKIA = -50; private static final int SOFT_KEY_LEFT_MOTOROLA = -21; private static final int SOFT_KEY_RIGHT_MOTOROLA = -22; private static final int SOFT_KEY_LEFT_MOTOROLA2 = -20; private static final int SOFT_KEY_LEFT_MOTOROLA1 = 21; private static final int SOFT_KEY_RIGHT_MOTOROLA1 = 22; private static final int SOFT_KEY_MIDLE_MOTOROLA = -23; private static final int SOFT_KEY_MIDLE_NOKIA = -5; private static final String SOFT_WORD = "SOFT"; /** * constructor. * here is predefining of spesial keys and platform made */ private KeyCodeAdapter() { adaptorCanvas = MainCanvas.getInstance(); PLATFORM_NAME = getPlatform(); SOFTKEY_LEFT = getLeftSoftkeyCode(); SOFTKEY_RIGHT = getRightSoftkeyCode(); SOFTKEY_MIDDLE_INTERNET = getMidleORInternetSoftkeyCode(); SOFTKEY_DELETE = getDeleteKeyCode(); SOFTKEY_BACK = getBackKeyCode(); } /** * return platform keycode of left softkey * if it's defined * default value -6 * * #return SOFTKEY_LEFT */ public int getPlatformSoftkeyLeftCode() { return SOFTKEY_LEFT; } /** * Returns mobile phone platform * * #return name mobile phone platform */ private String getPlatform() { // detecting NOKIA or SonyEricsson try { final String currentPlatform = System.getProperty("microedition.platform"); if (currentPlatform.indexOf("Nokia") != -1) { return PLATFORM_NOKIA; } else if (currentPlatform.indexOf("SonyEricsson") != -1) { return PLATFORM_SONY_ERICSSON; } } catch (Throwable ex) { } // detecting SAMSUNG try { Class.forName("com.samsung.util.Vibration"); return PLATFORM_SAMSUNG; } catch (Throwable ex) { } // detecting MOTOROLA try { Class.forName("com.motorola.multimedia.Vibrator"); return PLATFORM_MOTOROLA; } catch (Throwable ex) { try { Class.forName("com.motorola.graphics.j3d.Effect3D"); return PLATFORM_MOTOROLA; } catch (Throwable ex2) { try { Class.forName("com.motorola.multimedia.Lighting"); return PLATFORM_MOTOROLA; } catch (Throwable ex3) { try { Class.forName("com.motorola.multimedia.FunLight"); return PLATFORM_MOTOROLA; } catch (Throwable ex4) { } } } } try { if (adaptorCanvas.getKeyName(SOFT_KEY_LEFT_MOTOROLA).toUpperCase().indexOf(SOFT_WORD) > -1) { return PLATFORM_MOTOROLA; } } catch (Throwable e) { try { if (adaptorCanvas.getKeyName(SOFT_KEY_LEFT_MOTOROLA1).toUpperCase().indexOf(SOFT_WORD) > -1) { return PLATFORM_MOTOROLA; } } catch (Throwable e1) { try { if (adaptorCanvas.getKeyName(SOFT_KEY_LEFT_MOTOROLA2).toUpperCase().indexOf(SOFT_WORD) > -1) { return PLATFORM_MOTOROLA; } } catch (Throwable e2) { } } } // detecting SIEMENS try { Class.forName("com.siemens.mp.io.File"); return PLATFORM_SIEMENS; } catch (Throwable ex) { } // detecting LG try { Class.forName("mmpp.media.MediaPlayer"); return PLATFORM_LG; } catch (Throwable ex) { try { Class.forName("mmpp.phone.Phone"); return PLATFORM_LG; } catch (Throwable ex1) { try { Class.forName("mmpp.lang.MathFP"); return PLATFORM_LG; } catch (Throwable ex2) { try { Class.forName("mmpp.media.BackLight"); return PLATFORM_LG; } catch (Throwable ex3) { } } } } return PLATFORM_NOT_DEFINED; } /** * define real left soft key code by platform * * #return code */ private int getLeftSoftkeyCode() { int keyCode = 0; try { if (PLATFORM_NAME.equals(PLATFORM_MOTOROLA)) { String softkeyLeftMoto = ""; try { softkeyLeftMoto = adaptorCanvas.getKeyName(SOFT_KEY_LEFT_MOTOROLA).toUpperCase(); } catch (IllegalArgumentException ilae) { // ilae.printStackTrace(); } String softkeyLeftMoto1 = ""; try { softkeyLeftMoto1 = adaptorCanvas.getKeyName(SOFT_KEY_LEFT_MOTOROLA1).toUpperCase(); } catch (IllegalArgumentException ilae) { // ilae.printStackTrace(); } String softkeyLeftMoto2 = ""; try { softkeyLeftMoto2 = adaptorCanvas.getKeyName(SOFT_KEY_LEFT_MOTOROLA2).toUpperCase(); } catch (IllegalArgumentException ilae) { // ilae.printStackTrace(); } if (softkeyLeftMoto.indexOf(SOFT_WORD) >= 0 && softkeyLeftMoto.indexOf("1") >= 0) { return SOFT_KEY_LEFT_MOTOROLA; } else if (softkeyLeftMoto1.indexOf(SOFT_WORD) >= 0 && softkeyLeftMoto1.indexOf("1") >= 0) { return SOFT_KEY_LEFT_MOTOROLA1; } else if (softkeyLeftMoto2.indexOf(SOFT_WORD) >= 0 && softkeyLeftMoto2.indexOf("1") >= 0) { return SOFT_KEY_LEFT_MOTOROLA2; } else if (softkeyLeftMoto.indexOf(SOFT_WORD) >= 0 && softkeyLeftMoto.indexOf("LEFT") >= 0) { return SOFT_KEY_LEFT_MOTOROLA; } else if (softkeyLeftMoto1.indexOf(SOFT_WORD) >= 0 && softkeyLeftMoto1.indexOf("LEFT") >= 0) { return SOFT_KEY_LEFT_MOTOROLA1; } else if (softkeyLeftMoto2.indexOf(SOFT_WORD) >= 0 && softkeyLeftMoto2.indexOf("LEFT") >= 0) { return SOFT_KEY_LEFT_MOTOROLA2; } } else if (PLATFORM_NAME.equals(PLATFORM_NOKIA)) { return SOFT_KEY_LEFT_NOKIA; } else if (PLATFORM_NAME.equals(PLATFORM_SAMSUNG)) { // String leftkeySamsungName = adaptorCanvas.getKeyName(SOFT_KEY_LEFT_SAMSUNG).toUpperCase(); // if (leftkeySamsungName.indexOf(SOFT_WORD) >= 0) { // if (leftkeySamsungName.indexOf("1") >= 0) { return SOFT_KEY_LEFT_SAMSUNG; // } else if (leftkeySamsungName.indexOf("LEFT") >= 0) { // return SOFT_KEY_LEFT_SAMSUNG; // } // } } else if (PLATFORM_NAME.equals(PLATFORM_SIEMENS)) { String leftKeySiemensName = adaptorCanvas.getKeyName(SOFT_KEY_LEFT_SIEMENS).toUpperCase(); if (leftKeySiemensName.indexOf(SOFT_WORD) >= 0) { if (leftKeySiemensName.indexOf("1") >= 0) { return SOFT_KEY_LEFT_SIEMENS; } else if (leftKeySiemensName.indexOf("LEFT") >= 0) { return SOFT_KEY_LEFT_SIEMENS; } } } else if (PLATFORM_NAME.equals(PLATFORM_SONY_ERICSSON)) { return SOFT_KEY_LEFT_SE; } else if (PLATFORM_NAME.equals(PLATFORM_NOT_DEFINED)) { // for (int i = -125; i <= 125; i++) { if (i == 0) { i++; } // System.out.println(getKeyName(i).toUpperCase()); final String s = adaptorCanvas.getKeyName(i).toUpperCase(); if (s.indexOf(SOFT_WORD) >= 0) { if (s.indexOf("1") >= 0) { keyCode = i; break; } if (s.indexOf("LEFT") >= 0) { keyCode = i; break; } } } } if (keyCode == 0) { //#if emulator return SOFT_KEY_LEFT_NOKIA; //#endif } } catch (Throwable iaEx) { //#if emulator return SOFT_KEY_LEFT_NOKIA; //#endif } return keyCode; } /** * define real right soft key code for current platform * * #return code */ private int getRightSoftkeyCode() { int keyCode = 0; try { if (PLATFORM_NAME.equals(PLATFORM_MOTOROLA)) { String rightSoftMoto1 = ""; try { rightSoftMoto1 = adaptorCanvas.getKeyName(SOFT_KEY_LEFT_MOTOROLA1).toUpperCase(); } catch (IllegalArgumentException ilae) { // ilae.printStackTrace(); } String rightSoftMoto = ""; try { rightSoftMoto = adaptorCanvas.getKeyName(SOFT_KEY_RIGHT_MOTOROLA).toUpperCase(); } catch (IllegalArgumentException ilae) { // ilae.printStackTrace(); } String rightSoftMoto2 = ""; try { rightSoftMoto2 = adaptorCanvas.getKeyName(SOFT_KEY_RIGHT_MOTOROLA1).toUpperCase(); } catch (IllegalArgumentException ilae) { // ilae.printStackTrace(); } if (rightSoftMoto.indexOf(SOFT_WORD) >= 0 && rightSoftMoto.indexOf("2") >= 0) { return SOFT_KEY_RIGHT_MOTOROLA; } else if (rightSoftMoto1.indexOf(SOFT_WORD) >= 0 && rightSoftMoto1.indexOf("2") >= 0) { return SOFT_KEY_RIGHT_MOTOROLA; } else if (rightSoftMoto2.indexOf(SOFT_WORD) >= 0 && rightSoftMoto2.indexOf("2") >= 0) { return SOFT_KEY_RIGHT_MOTOROLA1; } else if (rightSoftMoto.indexOf(SOFT_WORD) >= 0 && rightSoftMoto.indexOf("RIGHT") >= 0) { return SOFT_KEY_LEFT_MOTOROLA; } else if (rightSoftMoto1.indexOf(SOFT_WORD) >= 0 && rightSoftMoto1.indexOf("RIGHT") >= 0) { return SOFT_KEY_RIGHT_MOTOROLA1; } else if (rightSoftMoto2.indexOf(SOFT_WORD) >= 0 && rightSoftMoto2.indexOf("RIGHT") >= 0) { return SOFT_KEY_RIGHT_MOTOROLA; } } else if (PLATFORM_NAME.equals(PLATFORM_NOKIA)) { return SOFT_KEY_RIGHT_NOKIA; } else if (PLATFORM_NAME.equals(PLATFORM_SAMSUNG)) { // String rightSoftSamsung = adaptorCanvas.getKeyName(SOFT_KEY_RIGHT_SAMSUNG).toUpperCase(); // if (rightSoftSamsung.indexOf(SOFT_WORD) >= 0) { // if (rightSoftSamsung.indexOf("2") >= 0) { return SOFT_KEY_RIGHT_SAMSUNG; // } else if (rightSoftSamsung.indexOf("RIGHT") >= 0) { // return SOFT_KEY_RIGHT_SAMSUNG; // } // } } else if (PLATFORM_NAME.equals(PLATFORM_SIEMENS)) { String rightSoftSiemens = adaptorCanvas.getKeyName(SOFT_KEY_RIGHT_SIEMENS).toUpperCase(); if (rightSoftSiemens.indexOf(SOFT_WORD) >= 0) { if (rightSoftSiemens.indexOf("4") >= 0) { return SOFT_KEY_RIGHT_SIEMENS; } else if (rightSoftSiemens.indexOf("RIGHT") >= 0) { return SOFT_KEY_RIGHT_SIEMENS; } } } else if (PLATFORM_NAME.equals(PLATFORM_SONY_ERICSSON)) { return SOFT_KEY_RIGHT_SE; } else if (PLATFORM_NAME.equals(PLATFORM_NOT_DEFINED)) { for (int i = -125; i <= 125; i++) { if (i == 0) { i++; } String keyName = adaptorCanvas.getKeyName(i).toUpperCase(); if (keyName.indexOf(SOFT_WORD) >= 0) { if (keyName.indexOf("2") >= 0) { keyCode = i; break; } else if (keyName.indexOf("4") >= 0) { keyCode = i; break; } else if (keyName.indexOf("RIGHT") >= 0) { keyCode = i; break; } } } } } catch (Throwable iaEx) { //#if emulator return SOFT_KEY_RIGHT_NOKIA; //#endif } return keyCode; } /** * define real middle soft key code for current platform * * #return code */ private int getMidleORInternetSoftkeyCode() { try { if (PLATFORM_NAME.equals(PLATFORM_MOTOROLA)) { if (adaptorCanvas.getKeyName(SOFT_KEY_MIDLE_MOTOROLA).toUpperCase().indexOf("SOFT") >= 0) { return SOFT_KEY_MIDLE_MOTOROLA; } } else if (PLATFORM_NAME.equals(PLATFORM_NOKIA)) { if (adaptorCanvas.getKeyName(SOFT_KEY_MIDLE_NOKIA).toUpperCase().indexOf("SOFT") >= 0) { return SOFT_KEY_MIDLE_NOKIA; } } else if (PLATFORM_NAME.equals(PLATFORM_SAMSUNG)) { } else if (PLATFORM_NAME.equals(PLATFORM_SIEMENS)) { } else if (PLATFORM_NAME.equals(PLATFORM_SONY_ERICSSON)) { return INTERNET_KEY_SE; } } catch (Throwable e) { } return 0; } /** * define real key's C or DELETE code for current platform * * #return code */ private int getDeleteKeyCode() { try { if (PLATFORM_NAME.equals(PLATFORM_MOTOROLA)) { } else if (PLATFORM_NAME.equals(PLATFORM_NOKIA)) { if (adaptorCanvas.getKeyName(DELETE_KEY_SE).toUpperCase().indexOf("CLEAR") >= 0) { return DELETE_KEY_NOKIA; } else { return DELETE_KEY_NOKIA; } } else if (PLATFORM_NAME.equals(PLATFORM_SAMSUNG)) { if (adaptorCanvas.getKeyName(DELETE_KEY_SAMSUNG).toUpperCase().indexOf("CLEAR") >= 0) { return DELETE_KEY_SAMSUNG; } } else if (PLATFORM_NAME.equals(PLATFORM_SIEMENS)) { } else if (PLATFORM_NAME.equals(PLATFORM_SONY_ERICSSON)) { if (adaptorCanvas.getKeyName(DELETE_KEY_SE).toUpperCase().indexOf("CLEAR") >= 0) { return DELETE_KEY_SE; } else if (adaptorCanvas.getKeyName(DELETE_KEY_SE).toUpperCase().indexOf("C") >= 0) { return DELETE_KEY_SE; } else { return DELETE_KEY_SE; } } } catch (Throwable e) { return DELETE_KEY_SE; } return 0; } /** * define real key's BACK code for current platform * * #return code */ private int getBackKeyCode() { try { if (PLATFORM_NAME.equals(PLATFORM_MOTOROLA)) { } else if (PLATFORM_NAME.equals(PLATFORM_NOKIA)) { } else if (PLATFORM_NAME.equals(PLATFORM_SAMSUNG)) { } else if (PLATFORM_NAME.equals(PLATFORM_SIEMENS)) { } else if (PLATFORM_NAME.equals(PLATFORM_SONY_ERICSSON)) { return BACK_KEY_SE; } } catch (Throwable e) { } return 0; } /** * name of curent platform * * #return PLATFORM_NAME */ public String getPlatformName() { return PLATFORM_NAME; } /** * Used to adopt key kode to predefined constances, which are platform independent. * <p/> * You can use this method in any kind of canvas, but better at first time to call * <code>getInstance()</code> method at the beginning of midlet work, because initialisation takes time. * <p/> * Best variant for usage is calling <code>adoptKeyCode()</code> to use <code>keyPressed()</code> method in Canvas: * <pre> * protected void keyPressed(int keyCode) { * keyCode = KeyCodeAdapter.getInstance().adoptKeyCode(keyCode); * } * </pre> * and then you can use it: * <pre> * switch (keyCode) { * case KeyCodeAdapter.UP_KEY: * break; * case KeyCodeAdapter.SOFT_KEY_LEFT: * break; * }</pre> * or send this code to any other clesses. * * #param keycode This code is sent by platform to canvas and redirected here * #return this keycode is equal to one of our constants declared in this class */ public int adoptKeyCode(int keycode) { switch (keycode) { case Canvas.KEY_NUM0: return KEY_0; case Canvas.KEY_NUM1: return KEY_1; case Canvas.KEY_NUM2: return KEY_2; case Canvas.KEY_NUM3: return KEY_3; case Canvas.KEY_NUM4: return KEY_4; case Canvas.KEY_NUM5: return KEY_5; case Canvas.KEY_NUM6: return KEY_6; case Canvas.KEY_NUM7: return KEY_7; case Canvas.KEY_NUM8: return KEY_8; case Canvas.KEY_NUM9: return KEY_9; case Canvas.KEY_STAR: return KEY__STAR; case Canvas.KEY_POUND: return KEY__POUND; default: if (keycode == SOFTKEY_LEFT) { return SOFT_KEY_LEFT; } else if (keycode == SOFTKEY_RIGHT) { return SOFT_KEY_RIGHT; } else if (keycode == SOFTKEY_DELETE) { return DELETE_KEY; } else if (keycode == SOFTKEY_BACK) { return BACK_KEY; } else if (keycode == SOFTKEY_MIDDLE_INTERNET) { return SOFT_KEY_MIDDLE_INTERNET; } else if (keycode == PENCIL_KEY_NOKIA) { return PENCIL_KEY; } else { try { final int gameAction; gameAction = adaptorCanvas.getGameAction(keycode); if (gameAction == Canvas.UP) { return UP_KEY; } else if (gameAction == Canvas.DOWN) { return DOWN_KEY; } else if (gameAction == Canvas.LEFT) { return LEFT_KEY; } else if (gameAction == Canvas.RIGHT) { return RIGHT_KEY; } else if (gameAction == Canvas.FIRE) { return CENTER_KEY; } } catch (IllegalArgumentException e) { // e.printStackTrace(); } } break; } //#if debug //# return keycode; //#else return NOT_DEFINED_KEY; //#endif } /** * return instance of class * * #return instance */ public static KeyCodeAdapter getInstance() { return instance; } } You have to use like this in your code:::- protected void keyPressed(int keyCode) { int internalKeyCode = KeyCodeAdapter.getInstance().adoptKeyCode(keyCode); switch (keyCode) { case KeyCodeAdapter.SOFT_KEY_LEFT: // some processing break; case KeyCodeAdapter.BACK_KEY: // some processing break; default: } ... } Hope this will help you. Thanks