edk2 cannot find i2c bus - i2c

I am new to UEFI and I am attempting to talk to an i2c bus on an Up eXtreme board. I have tried following people trying similar things with USB online but gBS->LocateHandleBuffer does not seem to find the i2c bus. I am led to assume that since i2c behaves differently to USB I may not be able to take the same approach with it, but I have no way of confirming my suspicions.
At this point any tips/pointers would be appreciated.
EFI_STATUS
EFIAPI
UefiMain(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE* SystemTable
)
{
EFI_STATUS Status;
EFI_HANDLE* HandleBuffer = NULL;
UINTN HandleCount = 17;
Print(L"HandleCount: %x\n", HandleCount);
Print(L"HandleBuffer: %x\n", HandleBuffer);
UINTN* freq = (UINTN*)23;
EFI_I2C_DEVICE* i2cDescriptor;
EFI_I2C_ENUMERATE_PROTOCOL* enumerateI2c;
Status = gBS->LocateHandleBuffer(ByProtocol,
&gEfiI2cEnumerateProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer);
if (EFI_ERROR(Status)) {
Print(L"ERROR: LocateHandleBuffer.\n");
Print(L"Status: %x\n", (int)Status);
Print(L"HandleCount: %x\n", HandleCount);
Print(L"HandleBuffer: %x\n", HandleBuffer);
return Status;
}
for (UINT8 Index = 0; Index < HandleCount; Index++) {
Status = gBS->HandleProtocol(HandleBuffer[Index],
&gEfiI2cEnumerateProtocolGuid,
(VOID**)&enumerateI2c);
if (EFI_ERROR(Status)) {
Print(L"ERROR: HandleProtocol.\n");
Print(L"Status: %x\n", (int)Status);
Print(L"HandleCount: %x\n", HandleCount);
Print(L"HandleBuffer: %x\n", HandleBuffer);
FreePool(HandleBuffer);
return Status;
}
Status = enumerateI2c->Enumerate(enumerateI2c, &i2cDescriptor);
Print(L"Starting to enumerate\n");
if (EFI_ERROR(Status)) {
Print(L"ERROR: Enumerate.\n");
Print(L"Status: %x\n", (int)Status);
Print(L"HandleCount: %x\n", HandleCount);
Print(L"HandleBuffer: %x\n", HandleBuffer);
FreePool(HandleBuffer);
return Status;
}
Print(L"Enumeration complete\nGetting Bus frequency\n");
Status = enumerateI2c->GetBusFrequency(enumerateI2c, i2cDescriptor->I2cBusConfiguration, freq);
if (EFI_ERROR(Status)) {
Print(L"ERROR: GetBusFrequency.\n");
Print(L"Status: %x\n", (int)Status);
FreePool(HandleBuffer);
return Status;
}
Print(L"Found Frequency:\n");
Print(L"%d\n", (CHAR16*)freq);
}
FreePool(HandleBuffer);
return EFI_SUCCESS;
}

not all UEFI features and drivers are supported on each UEFI firmware.
try to run the app on different hardwares, and see if they support the protocol.
sadly if the protocol does not exists, you have two options:
to implement the low level api.
find someone who has done what is written in 1.

Related

how to make HTTPS request in esp8266?

I once wanted to get THERMOCOUPLE DATA and by making HTTP request I put it on API
it worked flawlessly , here is the code for esp32:
// this example is public domain. enjoy! https://learn.adafruit.com/thermocouple/
#include "max6675.h"
#include <ArduinoJson.h>
#include <HTTPClient.h>
#include <WiFiMulti.h>
int thermoDO = 19;
int thermoCS = 23;
int thermoCLK = 5;
MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
const char *AP_SSID = "ssid";
const char *AP_PWD = "pass";
WiFiMulti wifiMulti;
void setup() {
Serial.begin(9600);
delay(4000);
wifiMulti.addAP(AP_SSID, AP_PWD);
Serial.println("MAX6675 test");
// wait for MAX chip to stabilize
delay(500);
}
void loop() {
// basic readout test, just print the current temp
Serial.print("C = ");
Serial.println(thermocouple.readCelsius());
Serial.print("F = ");
Serial.println(thermocouple.readFahrenheit());
// For the MAX6675 to update, you must delay AT LEAST 250ms between reads!
delay(1000);
postDataToServer();
}
void postDataToServer() {
Serial.println("Posting JSON data to server...");
// Block until we are able to connect to the WiFi access point
if (wifiMulti.run() == WL_CONNECTED) {
HTTPClient http;
http.begin("https://retoolapi.dev/fyXalF/data/1");
http.addHeader("Content-Type", "application/json");
StaticJsonDocument<200> doc;
// Add values in the document
//
doc["temp1"] = thermocouple.readCelsius();
doc["temp2"] = thermocouple.readFahrenheit();
String requestBody;
serializeJson(doc, requestBody);
int httpResponseCode = http.PUT(requestBody);
if(httpResponseCode>0){
String response = http.getString();
Serial.println(httpResponseCode);
Serial.println(response);
}
else {
Serial.printf("Error occurred while sending HTTP POST");
}
}
}
now I'm trying to do it by esp8266.
so the code is basically the same , you have to put "ESP8266" before library names and for making http.begin() you have to pass a WiFiClient beside API address :
// this example is public domain. enjoy! https://learn.adafruit.com/thermocouple/
#include "max6675.h"
#include <ArduinoJson.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WiFiMulti.h>
#include <WiFiClientSecure.h>
int thermoDO = 19;
int thermoCS = 23;
int thermoCLK = 5;
MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
const char *AP_SSID = "ssid";
const char *AP_PWD = "pass";
ESP8266WiFiMulti wifiMulti;
void setup() {
Serial.begin(9600);
delay(4000);
wifiMulti.addAP(AP_SSID, AP_PWD);
Serial.println("MAX6675 test");
// wait for MAX chip to stabilize
delay(500);
}
void loop() {
// basic readout test, just print the current temp
Serial.print("C = ");
Serial.println(thermocouple.readCelsius());
Serial.print("F = ");
Serial.println(thermocouple.readFahrenheit());
// For the MAX6675 to update, you must delay AT LEAST 250ms between reads!
delay(1000);
postDataToServer();
}
void postDataToServer() {
Serial.println("Posting JSON data to server...");
// Block until we are able to connect to the WiFi access point
if (wifiMulti.run() == WL_CONNECTED) {
WiFiClient client;
HTTPClient http;
http.begin(client,"https://retoolapi.dev/fyXalF/data/1");
http.addHeader("Content-Type", "application/json");
StaticJsonDocument<200> doc;
// Add values in the document
//
doc["temp1"] = thermocouple.readCelsius();
doc["temp2"] = thermocouple.readFahrenheit();
String requestBody;
serializeJson(doc, requestBody);
int httpResponseCode = http.PUT(requestBody);
if(httpResponseCode>0){
String response = http.getString();
Serial.println(httpResponseCode);
Serial.println(response);
}
else {
Serial.printf("Error occurred while sending HTTP POST");
}
}
}
it compiled but I got "bad request-400" and "The plain HTTP request was sent to HTTPS port" as a response .
I think the esp8266 library cant send https requests ...
any ideas how to solve this ?
PS : I also use #include <WiFiClientSecure.h>
WiFiClientSecure client;
HTTPClient http;
http.begin(client,"https://retoolapi.dev/0tvafA/data/1");
it's not working either : Error occurred while sending HTTP POSTC = 0.00
:(

MongoDB Atlas connection from mongoc (C) driver fails intermittently with 'No suitable servers found'

I'm using the MongoDB C driver (1.9.2) to connect to my Atlas Cluster (M5 using AWS).
My requests often succeeds, but I get this error about half the time. The longer I wait between requests, the more often the request succeeds.
I am always able to create a mongoc_client_t, but when the request fails, the drop, insert or read operation gets this error;
2019-12-30 23:10:50::dropCollection(): mongoc_collection_drop() failed code(13053)::
No suitable servers found: serverSelectionTimeoutMS expired: [Failed to receive length header from server. calling ismaster on 'xxxxx-shard-00-01-xxxxx.mongodb.net:27017'] [Failed to receive length header from server. calling ismaster on 'xxxxx-shard-00-00-xxxxx.mongodb.net:27017']
This is my (simplified) code;
I tried using a client pool, then switched to 'serverSelectionTryOnce=false' - they both get the error after timing out.
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <mongoc.h>
#include <bson.h>
#include <bcon.h>
#define ERROR -1
#define GOOD 0
typedef struct _MongoContext
{
mongoc_uri_t* uri;
mongoc_client_t* client;
mongoc_database_t* database;
mongoc_collection_t* collection;
bson_error_t error;
char* uriStr;
} MongoContext;
static const char* DEFAULT_URI = "mongodb+srv://<user>:<psswd>#<host>.mongodb.net/test?retryWrites=true&w=majority&serverSelectionTryOnce=false";
int getMongoContext(MongoContext* mctx, const char* dbname, const char* collname)
{
bson_error_t error;
mctx->uriStr = strdup(DEFAULT_URI);
mctx->uri = mongoc_uri_new_with_error(mctx->uriStr, &error);
if(!mctx->uri) {
fprintf(stderr, "getMongoContext(): Unable to parse URI(%s)\n(%s)", mctx->uriStr, error.message);
return ERROR;
}
// mongoc_client_pool_t *pool = mongoc_client_pool_new(mctx->uri);
// mongoc_client_pool_set_appname(pool, "my-mongo");
// mongoc_client_pool_set_error_api(pool, MONGOC_ERROR_API_VERSION_2);
// mctx->client = mongoc_client_pool_pop(pool);
mctx->client = mongoc_client_new_from_uri(mctx->uri);
if(!mctx->client) {
fprintf(stderr, "getMongoContext(): mongoc_client_new_from_uri() failed(%s)", error.message);
return ERROR;
}
mongoc_client_set_appname(mctx->client, "my-mongo");
mctx->database = mongoc_client_get_database(mctx->client, dbname);
if(mctx->database == NULL) {
fprintf(stderr, "getMongoContext(): invalid database(%s)", dbname);
return ERROR;
}
mctx->collection = mongoc_client_get_collection(mctx->client, dbname, collname);
if(mctx->collection == NULL) {
fprintf(stderr, "getMongoContext(): invalid collection(%s)", collname);
}
char* ptr = strchr(mctx->uriStr, '#');
fprintf(stderr, "getMongoContext(): connection made for host(%s), db(%s), collection(%s)\n", (ptr+1), dbname, collname);
return GOOD;
}
void closeMongoContext(MongoContext* mctx)
{
mongoc_collection_destroy(mctx->collection);
mongoc_database_destroy(mctx->database);
mongoc_uri_destroy(mctx->uri);
mongoc_client_destroy(mctx->client);
mongoc_cleanup();
free(mctx->uriStr);
}
/**
* read the collection in the given MongoContext
*/
int readCollection(MongoContext* mctx)
{
mongoc_cursor_t* cursor;
const bson_t* doc;
char* str;
bson_t* query = bson_new();
cursor = mongoc_collection_find_with_opts(mctx->collection, query, NULL, NULL);
if(cursor == NULL) {
fprintf(stderr, "readCollection(): Unable to retrieve a cursor for collection(%s)",
mongoc_collection_get_name(mctx->collection));
return ERROR;
}
while(mongoc_cursor_next(cursor, &doc)) {
str = bson_as_canonical_extended_json(doc, NULL);
printf("%s\n", str);
bson_free(str);
}
bson_destroy(query);
mongoc_cursor_destroy(cursor);
return GOOD;
}
int insertIntoCollection(MongoContext* mctx, const char* jsondata)
{
bson_t* doc;
bson_t reply;
bson_error_t error;
doc = bson_new_from_json((const uint8_t*)jsondata, -1, &error);
if(!doc) {
fprintf(stderr, "insertIntoCollection(): bson_new_from_json() failed (%s)\n", error.message);
return ERROR;
}
fprintf(stderr, "insertIntoCollection(): insert into collection(%s)\n", mongoc_collection_get_name(mctx->collection));
bool b = mongoc_collection_insert_one(mctx->collection, doc, NULL, &reply, &error);
if(!b) {
fprintf(stderr, "insertIntoCollection(): mongoc_collection_insert_one() failed (%s)\n", error.message);
}
bson_destroy(doc);
return GOOD;
}
int dropCollection(MongoContext* mctx)
{
bson_error_t error;
bool rval = mongoc_collection_drop(mctx->collection, &error);
if(!rval) {
fprintf(stderr, "dropCollection(): mongoc_collection_drop() failed code(%d)::%s", error.code, error.message);
fprintf(stderr, "dropCollection(): mongoc_collection_drop() failed on collection(%s) for(%s)",
mongoc_collection_get_name(mctx->collection), mctx->uriStr);
return (error.code == 26) ? GOOD : ERROR;
}
return GOOD;
}
int main(int argc, char* argv[])
{
mongoc_init();
MongoContext mctx = {0};
getMongoContext(&mctx, "my-db", "my-collection");
if(dropCollection(&mctx) == ERROR) {
exit(1);
}
printf("collection dropped...\n");
if(insertIntoCollection(&mctx, "{ \"hello\" : \"world\" }") == ERROR) {
exit(1);
}
printf("inserted into collection...\n");
if(readCollection(&mctx) == ERROR) {
exit(1);
}
closeMongoContext(&mctx);
}
In my case it was a version issue. I had to upgrade my C driver version to be compatible with the server.

Windows Service is working fine with character set as unicode but same code with multi-byte is start to failed with 1053 error

The basic windows service example code in c++ with release configuration + unicode character set is perfectly start using sc start cmd in admin console but when i change the configuration release+ multi-byte than sc start cmd fail with most common service error : 1053 -The service did not respond to the start or control request in a timely fashion.
I don't know what is the relation between this unicode vs multi-byte config. even i have cross-check each function suffix and that is expected like in unicode mode suffix is W and in multi-byte mode suffix is A
#define SERVICE_NAME "USB Device Monitor Service"
#define SLEEP_TIME (1000)
void main()
{
SERVICE_TABLE_ENTRY ServiceTable[1];
ServiceTable[0].lpServiceName = SERVICE_NAME;
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
StartServiceCtrlDispatcher(ServiceTable);
}
void ServiceMain()
{
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
Status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
Status.dwCurrentState = SERVICE_START_PENDING;
Status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
Status.dwWin32ExitCode = 0;
Status.dwServiceSpecificExitCode = 0;
Status.dwCheckPoint = 0;
Status.dwWaitHint = 0;
hStatus = RegisterServiceCtrlHandlerEx(SERVICE_NAME, (LPHANDLER_FUNCTION_EX)ControlHandler, 0);
if ((SERVICE_STATUS_HANDLE)0 == hStatus)
{
// Error
}
SetServiceStatus(hStatus, &Status);
Status.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(hStatus, &Status);
ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
// Initialization
hDeviceNotify = RegisterDeviceNotification((HANDLE)hStatus, &NotificationFilter, DEVICE_NOTIFY_SERVICE_HANDLE);
if (NULL == hDeviceNotify)
{
// Error
}
while (SERVICE_RUNNING == Status.dwCurrentState)
{
Sleep(SLEEP_TIME);
}
}
DWORD ControlHandler(DWORD dwControl, DWORD dwEventType,
LPVOID lParam, LPVOID lpContext)
{
switch (dwControl)
{
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
UnregisterDeviceNotification(hDeviceNotify);
Status.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(hStatus, &Status);
CloseHandle(hPipe);
return NO_ERROR;
case SERVICE_CONTROL_DEVICEEVENT:
if ((DBT_DEVICEARRIVAL == dwEventType) || (DBT_DEVICEREMOVECOMPLETE == dwEventType))
{
try
{
DEV_BROADCAST_HDR* header = reinterpret_cast<DEV_BROADCAST_HDR*>(lParam);
if (DBT_DEVTYP_DEVICEINTERFACE == header->dbch_devicetype)
{
//parse intrested USB device only
}
}
catch (const std::nullptr_t /*ex*/)
{
//"ERROR: Processing WM_DEVICECHANGE failed
}
}
break;
default:
//"ERROR : Unknown dwControl: dwControl)
SetServiceStatus(hStatus, &Status);
break;
}
return NO_ERROR;
}
Your ServiceMain() and ControlHandler() functions are declared wrong, but you are using type-casts to stop the compiler from complaining. Any time you have to resort to using a type-cast to quiet the compiler, think about what your code is trying to do, as it is likely doing something wrong.
Also, the SERVICE_TABLE_ENTRY[] array that you are passing to StartServiceCtrlDispatcher() is incomplete - you are not NULL-terminating the array, like the documentation says to do.
For that matter, you claim that your service works when compiling for Unicode, but the code you have shown won't actually compile under Unicode, because the ServiceTable[0].lpServiceName field will be expecting a Unicode string but the code shown is assigning an ANSI string instead, which is an error.
I suggest you read Microsoft's documentation, and pay close attention to the examples it gives:
Service Program Tasks
The following tasks are performed by service programs:
Writing a Service Program's main Function
Writing a ServiceMain Function
Writing a Control Handler Function
Related Topics
The Complete Service Sample
With that said, try something more like this:
#define SERVICE_NAME TEXT("USB Device Monitor Service")
HANDLE hStopEvent = NULL;
SERVICE_STATUS_HANDLE hStatus = NULL;
SERVICE_STATUS Status;
DWORD WINAPI ControlHandler(DWORD dwControl, DWORD dwEventType,
LPVOID lParam, LPVOID lpContext)
{
switch (dwControl)
{
case SERVICE_CONTROL_INTERROGATE:
return NO_ERROR;
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
SetEvent(hStopEvent);
return NO_ERROR;
case SERVICE_CONTROL_DEVICEEVENT:
if ((DBT_DEVICEARRIVAL == dwEventType) || (DBT_DEVICEREMOVECOMPLETE == dwEventType))
{
try
{
DEV_BROADCAST_HDR* header = reinterpret_cast<DEV_BROADCAST_HDR*>(lParam);
if (DBT_DEVTYP_DEVICEINTERFACE == header->dbch_devicetype)
{
//parse intrested USB device only
}
}
catch (const std::nullptr_t /*ex*/)
{
//"ERROR: Processing WM_DEVICECHANGE failed
}
}
break;
default:
//"ERROR : Unknown dwControl: dwControl)
break;
}
return NO_ERROR;
}
void WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
{
hStatus = RegisterServiceCtrlHandlerEx(SERVICE_NAME, &ControlHandler, 0);
if (!hStatus)
{
// Error
return;
}
ZeroMemory(&Status, sizeof(Status));
Status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
Status.dwCurrentState = SERVICE_START_PENDING;
SetServiceStatus(hStatus, &Status);
// Initialization
hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!hStopEvent)
{
// Error
Status.dwCurrentState = SERVICE_STOPPED;
Status.dwWin32ExitCode = GetLastError();
SetServiceStatus(hStatus, &Status);
return;
}
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
HDEVNOTIFY hDeviceNotify = RegisterDeviceNotification((HANDLE)hStatus, &NotificationFilter, DEVICE_NOTIFY_SERVICE_HANDLE);
if (!hDeviceNotify)
{
// Error
Status.dwCurrentState = SERVICE_STOPPED;
Status.dwWin32ExitCode = GetLastError();
SetServiceStatus(hStatus, &Status);
return;
}
Status.dwCurrentState = SERVICE_RUNNING;
Status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
SetServiceStatus(hStatus, &Status);
WaitForSingleObject(hStopEvent, INFINITE);
Status.dwCurrentState = SERVICE_STOP_PENDING;
Status.dwControlsAccepted = 0;
SetServiceStatus(hStatus, &Status);
UnregisterDeviceNotification(hDeviceNotify);
CloseHandle(hStopEvent);
Status.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(hStatus, &Status);
}
int main()
{
SERVICE_TABLE_ENTRY ServiceTable[2];
ServiceTable[0].lpServiceName = SERVICE_NAME;
ServiceTable[0].lpServiceProc = &ServiceMain;
ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;
StartServiceCtrlDispatcher(ServiceTable);
return 0;
}

pci_disable_msi Oops Bug

I am trying to write a kernel module that will handle MSI interrupts for a PCIe device. I have written a simple skeleton outline for my driver currently and whenever I try to call 'pci_disable_msi(dev)' I get an unable to handle kernel NULL pointer dereference error. I am following along exactly as described from the /Documentation/PCI/MSI-HOWTO.txt and it seems to me that I should not be getting this error. Is this a bug or is my setup incorrect? Judging by the last print that occures, I am pretty sure that it is happening at the fpga_remove() when I call pci_disable_msi(). (Clearly this occures when I am removing the module)
static struct pci_driver fpga_driver = {
.name = "PCIe_test",
.id_table = fpga_dev_table,
.probe = fpga_probe,
.remove = fpga_remove,
.suspend = fpga_suspend,
.resume = fpga_resume,
};
static irqreturn_t fpga_isr(int irq, struct pci_dev *dev)
{
printk(KERN_NOTICE "THIS is the ISR\n");
return IRQ_HANDLED;
}
static int setup_MSI_interrupt(struct pci_dev *dev, int num_msi)
{
int result;
result = pci_enable_msi(dev);
if(result)
{
printk(KERN_WARNING "Could not enable MSI\n");
return result;
}
printk(KERN_NOTICE "MSI has been enabled\n");
printk(KERN_NOTICE "dev->irq line is %d", dev->irq);
result = request_irq(dev->irq, fpga_isr, IRQF_SHARED, fpga_driver.name, dev);
printk(KERN_NOTICE "Using IRQ num %d\n", dev->irq);
if (result) {
dev_err(&dev->dev, "Failed to allocate irq %d: %d\n", dev->irq, result);
goto exit1;
}
dev_info(&dev->dev, "FPGA using PCIe Interrupt\n");
return 0;
exit1:
return -1;
}
static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
printk(KERN_NOTICE "Probing driver\n");
switch(dev->vendor) {
case VENDOR://0x1708:
printk(KERN_NOTICE "Xilinx device found\n");
break;
default:
printk(KERN_NOTICE "Device found that does not match id: id = 0x%04X\n", dev->device);
};
int err = pci_enable_device(dev);
if (err) {
dev_err(&dev->dev, "Failed to enable FPGA PCI device (%d)\n", err);
goto exit;
}
err = setup_MSI_interrupt(dev, NUM_MSI);
if(err)
goto exit;
return 0;
exit:
return -1;
}
static void fpga_remove(struct pci_dev *dev)
{
printk(KERN_NOTICE "REMOVING IRQ # %d\n", dev->irq);
free_irq(dev->irq, dev);
printk(KERN_NOTICE "IRQ has been freed\n");
pci_disable_msi(dev); // This causes a NUll Pointer to be dereferenced but needs to be added
printk(KERN_NOTICE "MSI has been disabled\n");
}
static int __init fpga_init(void)
{
printk(KERN_NOTICE "Registering Driver\n");
return pci_register_driver(&fpga_driver);
return 0;
}
You should probably not use the struct pci_dev as void *dev_id parameter in the request_irq(...) and the free_irq(...) functions. Its important to call them with the right and the same unique dev_id parameter for the interrupt. Doing this not could cause the kernel panic at pci_disable_msi() on removing the module.
Read more here:
What is dev_id parameter in request_irq?

Boost io_service stopping?

I am working on an NPAPI plugin that allows to use sockets with local inside browsers and I am using Boost sockets for this.
My usage right now is just open the socket write a meesage, read, send a closing message and close and then repeat (I know it is stupid to close and open everytime but I can not change that).
The problem is that after the second open I am unable to read from the socket, until las changes I was able to open write but never got the info back and now it seems the io_service thread is just dying.
I have read a lot of tutorial and info, but no one seems to open several client sockets as I am trying to do.
Here are the class that stores the socket info and handler:
SocketInfo.hpp
class SocketInfo
{
public:
void start_read();
void handle_read(const boost::system::error_code& error, std::size_t bytes_transferred);
FB::JSObjectPtr m_callback;
boost::shared_ptr<boost::asio::ip::tcp::socket> m_socket;
char data_[SOCKETS_API_BUFFER];
int key;
boost::shared_ptr<SocketsAPI> parent;
};
SocketInfo.cpp
void SocketInfo::start_read()
{
parent->log("start_read" + boost::lexical_cast<std::string>(key));
m_socket->async_receive(boost::asio::buffer(data_, SOCKETS_API_BUFFER),
boost::bind(&SocketInfo::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void SocketInfo::handle_read(const boost::system::error_code& error,
std::size_t bytes_transferred)
{
if (!error) {
parent->log("handle_read" + boost::lexical_cast<std::string>(key));
std::string str(&data_[0], &data_[0] + bytes_transferred);
m_callback->InvokeAsync("processData", FB::variant_list_of(str));
start_read();
} else {
parent->log("error closing " + boost::lexical_cast<std::string>(key));
m_callback->InvokeAsync("processCancel", FB::variant_list_of());
parent->do_close(*this);
}
}
SocketApi.h
class SocketsAPI : public FB::JSAPIAuto
{
public:
SocketsAPI(const SocketsPtr& plugin, const FB::BrowserHostPtr& host) :
m_plugin(plugin), m_host(host)
{
... FireBreath code here ...
//Start thread with work
workPtr.reset( new boost::asio::io_service::work(io_service));
ioThreadPtr.reset(new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service)));
}
virtual ~SocketsAPI() {
workPtr.reset();
if (ioThreadPtr) {
ioThreadPtr->join();
}
};
//Socket Methods
int open(const int port, const FB::JSObjectPtr &callback );
void close(const int key);
void write(const int key, const std::string data);
// Method echo
FB::variant echo(const FB::variant& msg);
void do_close(const SocketInfo socket);
void log(const std::string &str);
private:
mapType sockets;
boost::asio::io_service io_service;
boost::shared_ptr<boost::thread> ioThreadPtr;
boost::shared_ptr<boost::asio::io_service::work> workPtr;
void checkOpen(const SocketInfo socket);
void do_write(const std::string data, const SocketInfo socket);
void start_read(const SocketInfo socket);
void empty_handle(const boost::system::error_code& error);
int getFirstEmpty();
SocketInfo getSocket(const int key);
};
SocketAPI.cpp
int SocketsAPI::open(const int port, const FB::JSObjectPtr &callback )
{
log("open");
boost::shared_ptr<SocketInfo> socket;
socket.reset(new SocketInfo);
socket->m_socket.reset(new boost::asio::ip::tcp::socket(io_service));
socket->m_callback = callback;
ip::tcp::endpoint tcp(ip::address::from_string("127.0.0.1"), port);
boost::system::error_code errorcode;
socket->m_socket->connect(tcp, errorcode);
if (errorcode) {
trace("Connection failed: ", errorcode.message());
return -1;
}
log("conenected");
boost::asio::socket_base::keep_alive o(true);
socket->m_socket->set_option(o);
int key = getFirstEmpty();
socket->key = key;
socket->parent.reset(this);
sockets.insert ( std::pair<int,boost::shared_ptr<SocketInfo>>(key,socket));
socket->start_read();
if (io_service.stopped()) {
log("Resetting service");
io_service.reset();
}
return key;
}
void SocketsAPI::close(const int key)
{
SocketInfo socket = getSocket(key);
checkOpen(socket);
log("close");
io_service.post(boost::bind(&SocketsAPI::do_close, this, socket));
}
void SocketsAPI::write(const int key, const std::string data)
{
log("write socket " + boost::lexical_cast<std::string>(key));
SocketInfo socket = getSocket(key);
checkOpen(socket);
io_service.post(boost::bind(&SocketsAPI::do_write, this, Base64::decode(data), socket));
}
void SocketsAPI::checkOpen(const SocketInfo socket)
{
log("checkOpen");
if (!socket.m_socket || !socket.m_socket->is_open()) {
trace("Socket not opened", "");
throw FB::script_error("There is no open socket");
}
}
void SocketsAPI::do_write(const std::string data,
const SocketInfo socket)
{
log("do_write " + boost::lexical_cast<std::string>(socket.key));
if (!socket.m_socket->is_open()) {
return;
}
boost::asio::async_write(*(socket.m_socket.get()),
boost::asio::buffer(&data[0], data.size()),
boost::bind(&SocketsAPI::empty_handle, this, boost::asio::placeholders::error)
);
}
void SocketsAPI::empty_handle(const boost::system::error_code& error)
{
if (error) {
trace("Error writing: ", error.message());
}
}
void SocketsAPI::do_close(const SocketInfo socket)
{
log("do_close");
if (!socket.m_socket || !socket.m_socket->is_open()) {
return;
}
boost::system::error_code errorcode;
socket.m_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, errorcode);
if (errorcode) {
trace("Closing failed: ", errorcode.message());
}
socket.m_socket->close(errorcode);
if (errorcode) {
trace("Closing2 failed: ", errorcode.message());
}
mapType::iterator iter = sockets.find(socket.key);
if (iter != sockets.end()) {
sockets.erase (iter);
}
log("do_close end");
}
int SocketsAPI::getFirstEmpty() {
int i = 0;
mapType::iterator iter;
while(true) {
iter = sockets.find(i);
if (iter == sockets.end()) {
return i;
}
i++;
}
}
SocketInfo SocketsAPI::getSocket(const int key) {
mapType::iterator iter = sockets.find(key);
if (iter == sockets.end()) {
trace("Socket not found", "");
throw FB::script_error("Socket not found");
}
log("socket " + boost::lexical_cast<std::string>(key) +" found");
return *iter->second.get();
}
I am sure that something could be improved (please tell me) but I can not find the error why after the second open it just doesn't work.
Traces of excution:
open
conenected
start_read0
write socket 0
socket 0 found
checkOpen
do_write 0
handle_read0
start_read0
write socket 0
socket 0 found
checkOpen
do_write 0
socket 0 found
checkOpen
close
do_close
do_close end
open
conenected
start_read0
write socket 0
socket 0 found
checkOpen
It seems that io_service.run() just stops but the thread is still working and io_service is not stopped so I am not sure what could be happening.
Ok I found the error it was a lot simpler than I thought it just throw an exception and that stop everything but as I was using it inside a browser I didn't notice that.
Still I am unable to solve the problem so you can check: Boost bind object freed on read handler to share some insight.