From c1e9edd2de659b4b00ebd199edeae5e7d76822e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Denis?= <¨denisguimaraes2012@gmail.com¨> Date: Mon, 11 May 2026 20:27:40 -0400 Subject: [PATCH 01/23] add esp32 vendor and product ID --- .gitignore | 5 +++++ smartlamp-kernel-module/probe_2025.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index a7dfe2b..a9c0c84 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,7 @@ smartlamp-brightnessd/ tasks-daemon-2026/ +.probe_2025* +probe_2025* +.*.cmd +Module.symvers +modules.order \ No newline at end of file diff --git a/smartlamp-kernel-module/probe_2025.c b/smartlamp-kernel-module/probe_2025.c index de1e623..412728b 100644 --- a/smartlamp-kernel-module/probe_2025.c +++ b/smartlamp-kernel-module/probe_2025.c @@ -14,8 +14,8 @@ static uint usb_in, usb_out; // Endereços das portas de e static char *usb_in_buffer, *usb_out_buffer; // Buffers de entrada e saída da USB static int usb_max_size; // Tamanho máximo de uma mensagem USB -#define VENDOR_ID SUBSTITUA_PELO_VENDORID /* Encontre o VendorID do smartlamp */ -#define PRODUCT_ID SUBSTITUA_PELO_PRODUCTID /* Encontre o ProductID do smartlamp */ +#define VENDOR_ID 0x10c4 /* Encontre o VendorID do smartlamp */ +#define PRODUCT_ID 0xea60 /* Encontre o ProductID do smartlamp */ static const struct usb_device_id id_table[] = { { USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, {} }; static int usb_probe(struct usb_interface *ifce, const struct usb_device_id *id); // Executado quando o dispositivo é conectado na USB From f35812bbfe5c5e78b01c1f04d617fc95b68e61fc Mon Sep 17 00:00:00 2001 From: mello Date: Mon, 11 May 2026 20:41:55 -0400 Subject: [PATCH 02/23] feature: read serial --- esp32/.gitignore | 5 ++++ esp32/.vscode/extensions.json | 10 ++++++++ esp32/include/README | 37 ++++++++++++++++++++++++++++ esp32/lib/README | 46 +++++++++++++++++++++++++++++++++++ esp32/pinos.txt | 0 esp32/platformio.ini | 16 ++++++++++++ esp32/src/main.cpp | 29 ++++++++++++++++++++++ esp32/test/README | 11 +++++++++ 8 files changed, 154 insertions(+) create mode 100644 esp32/.gitignore create mode 100644 esp32/.vscode/extensions.json create mode 100644 esp32/include/README create mode 100644 esp32/lib/README delete mode 100644 esp32/pinos.txt create mode 100644 esp32/platformio.ini create mode 100644 esp32/src/main.cpp create mode 100644 esp32/test/README diff --git a/esp32/.gitignore b/esp32/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/esp32/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/esp32/.vscode/extensions.json b/esp32/.vscode/extensions.json new file mode 100644 index 0000000..080e70d --- /dev/null +++ b/esp32/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" + ] +} diff --git a/esp32/include/README b/esp32/include/README new file mode 100644 index 0000000..49819c0 --- /dev/null +++ b/esp32/include/README @@ -0,0 +1,37 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the convention is to give header files names that end with `.h'. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/esp32/lib/README b/esp32/lib/README new file mode 100644 index 0000000..9379397 --- /dev/null +++ b/esp32/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into the executable file. + +The source code of each library should be placed in a separate directory +("lib/your_library_name/[Code]"). + +For example, see the structure of the following example libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional. for custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +Example contents of `src/main.c` using Foo and Bar: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +The PlatformIO Library Dependency Finder will find automatically dependent +libraries by scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/esp32/pinos.txt b/esp32/pinos.txt deleted file mode 100644 index e69de29..0000000 diff --git a/esp32/platformio.ini b/esp32/platformio.ini new file mode 100644 index 0000000..ed64f7f --- /dev/null +++ b/esp32/platformio.ini @@ -0,0 +1,16 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp32dev] +platform = espressif32 +board = esp32dev +framework = arduino +upload_speed = 115200 +monitor_speed = 115200 diff --git a/esp32/src/main.cpp b/esp32/src/main.cpp new file mode 100644 index 0000000..429f563 --- /dev/null +++ b/esp32/src/main.cpp @@ -0,0 +1,29 @@ +#include + +const int baudrate = 115200; +const int ledPin = 13; +const int ldrPin = 36; + +void setup() { + Serial.begin(baudrate); + // Serial.println("Hello World!"); + Serial.println("Write something: "); + pinMode(ledPin, OUTPUT); + pinMode(ldrPin, INPUT); +} + +void loop() { + if (Serial.available() > 0) { + String input = Serial.readString(); + Serial.println("You wrote: " + input); + } + + // digitalWrite(ledPin, HIGH); + // delay(1000); + // digitalWrite(ledPin, LOW); + delay(100); + + int value = analogRead(ldrPin); + Serial.println(value); + +} \ No newline at end of file diff --git a/esp32/test/README b/esp32/test/README new file mode 100644 index 0000000..9b1e87b --- /dev/null +++ b/esp32/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html From 4a1779a16c84aa56aad8001b3db3e92856af1e7c Mon Sep 17 00:00:00 2001 From: Bianca Peres Date: Wed, 13 May 2026 01:42:58 -0400 Subject: [PATCH 03/23] Update usb write serial function --- smartlamp-kernel-module/serial_write_2025.c | 27 ++++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/smartlamp-kernel-module/serial_write_2025.c b/smartlamp-kernel-module/serial_write_2025.c index 369359f..224be28 100644 --- a/smartlamp-kernel-module/serial_write_2025.c +++ b/smartlamp-kernel-module/serial_write_2025.c @@ -98,7 +98,14 @@ static int usb_probe(struct usb_interface *interface, const struct usb_device_id // TASK 2.2: Chame a função usb_write_serial para enviar o comando SET_LED com valor 100 // Descomente a linha abaixo e implemente a função usb_write_serial - // ret = usb_write_serial("SET_LED", 100); + ret = usb_write_serial("SET_LED", 100); + if (ret) + { + printk(KERN_ERR "SmartLamp: Falha ao escrever no serial\n"); + kfree(usb_in_buffer); + kfree(usb_out_buffer); + return ret; + } return 0; } @@ -116,11 +123,23 @@ static void usb_disconnect(struct usb_interface *interface) { static int usb_write_serial(char *cmd, int param) { int ret, actual_size; + sprintf(usb_out_buffer, "%s %d", cmd, param); + printk(KERN_INFO "SmartLamp: Enviando comando: %s %d\n", cmd, param); - // TASK 2.2: Implemente o envio do comando para o dispositivo - // Dica: Formate o comando no buffer usb_out_buffer e envie usando usb_bulk_msg - // O formato esperado é: "COMANDO PARAMETRO\n" + ret = usb_bulk_msg( + smartlamp_device, + usb_sndbulkpipe(smartlamp, usb_out), + usb_out_buffer, + strlen(usb_out_buffer), + &actual_size, + 1000 + ); + + if (ret) { + printk(KERN_ERR "SmartLamp: Erro de codigo %d ao enviar comando!\n", ret); + return -1; + } return 0; } From a7ca49036898d365ca0f5242c0fbd9cd1548d276 Mon Sep 17 00:00:00 2001 From: Vitor Aguiar Date: Tue, 12 May 2026 10:34:10 -0400 Subject: [PATCH 04/23] refactor: changed object makefile to actual task --- smartlamp-kernel-module/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smartlamp-kernel-module/Makefile b/smartlamp-kernel-module/Makefile index 23d5281..2a39360 100644 --- a/smartlamp-kernel-module/Makefile +++ b/smartlamp-kernel-module/Makefile @@ -6,7 +6,7 @@ # Tarefa 2.3: obj-m += serial_read_2025.o # Tarefa 2.4: obj-m += sysfs_2025.o # Tarefa 3.1: obj-m += test_driver.o -obj-m += ALTERE_PARA_O_ARQUIVO_DA_TASK.o +obj-m += obj-m += test_driver.o PWD := $(CURDIR) all: From 15a64210ef1520fcb1a3bf32e0ce96ce462a8b22 Mon Sep 17 00:00:00 2001 From: Vitor Aguiar Date: Tue, 12 May 2026 10:59:49 -0400 Subject: [PATCH 05/23] Revert "refactor: changed object makefile to actual task" This reverts commit 00dd24bc368715bc68f5f59aba3691613e7ca22b. --- smartlamp-kernel-module/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smartlamp-kernel-module/Makefile b/smartlamp-kernel-module/Makefile index 2a39360..23d5281 100644 --- a/smartlamp-kernel-module/Makefile +++ b/smartlamp-kernel-module/Makefile @@ -6,7 +6,7 @@ # Tarefa 2.3: obj-m += serial_read_2025.o # Tarefa 2.4: obj-m += sysfs_2025.o # Tarefa 3.1: obj-m += test_driver.o -obj-m += obj-m += test_driver.o +obj-m += ALTERE_PARA_O_ARQUIVO_DA_TASK.o PWD := $(CURDIR) all: From c969035b8d9f4b75110ab9d096e12064af58740d Mon Sep 17 00:00:00 2001 From: Vitor Aguiar Date: Tue, 12 May 2026 11:01:58 -0400 Subject: [PATCH 06/23] refactor: added the proper target object for driver mock3.1 --- smartlamp-kernel-module/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smartlamp-kernel-module/Makefile b/smartlamp-kernel-module/Makefile index 23d5281..4408c31 100644 --- a/smartlamp-kernel-module/Makefile +++ b/smartlamp-kernel-module/Makefile @@ -6,7 +6,7 @@ # Tarefa 2.3: obj-m += serial_read_2025.o # Tarefa 2.4: obj-m += sysfs_2025.o # Tarefa 3.1: obj-m += test_driver.o -obj-m += ALTERE_PARA_O_ARQUIVO_DA_TASK.o +obj-m += test_driver.o PWD := $(CURDIR) all: From b6eece5c080af52d8cb89d3621064ddb85449c59 Mon Sep 17 00:00:00 2001 From: Vitor Aguiar Date: Tue, 12 May 2026 13:58:07 -0400 Subject: [PATCH 07/23] feat: added mock variables to driver mocking --- smartlamp-kernel-module/test_driver.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/smartlamp-kernel-module/test_driver.c b/smartlamp-kernel-module/test_driver.c index b9ffe40..754717d 100644 --- a/smartlamp-kernel-module/test_driver.c +++ b/smartlamp-kernel-module/test_driver.c @@ -14,6 +14,10 @@ static struct kobj_attribute led_attribute = __ATTR(led, 0664, attr_show, attr_s static struct kobj_attribute ldr_attribute = __ATTR(ldr, 0664, attr_show, attr_store); static struct kobj_attribute threshold_attribute = __ATTR(threshold, 0664, attr_show, attr_store); +static int mock_led = 0; +static int mock_ldr = 0; +static int mock_threshold = 0; + static struct attribute *attrs[] = { &led_attribute.attr, &ldr_attribute.attr, From 1752919bb4d25650ae97fc69d9473d2aa056ae08 Mon Sep 17 00:00:00 2001 From: Vitor Aguiar Date: Tue, 12 May 2026 13:58:36 -0400 Subject: [PATCH 08/23] feat: added conditional values to print --- smartlamp-kernel-module/test_driver.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/smartlamp-kernel-module/test_driver.c b/smartlamp-kernel-module/test_driver.c index 754717d..00ef6a9 100644 --- a/smartlamp-kernel-module/test_driver.c +++ b/smartlamp-kernel-module/test_driver.c @@ -51,6 +51,15 @@ static ssize_t attr_show(struct kobject *sys_obj, struct kobj_attribute *attr, c (void)sys_obj; (void)attr_name; + if(strcmp(attr_name,"ldr")) { + value = mock_ldr; + } + if(strcmp(attr_name,"led")) { + value = mock_led; + } + if(strcmp(attr_name,"threshold")) { + value = mock_threshold; + } // TASK 3.1: esta funcao e chamada quando o usuario le um arquivo com cat. // Exemplo: cat /sys/kernel/smartlamp/ldr // From 2dde054ccaf60c4ab0a9a007ecf1a54dfc187e03 Mon Sep 17 00:00:00 2001 From: Vitor Aguiar Date: Tue, 12 May 2026 13:59:36 -0400 Subject: [PATCH 09/23] feat: added conditional values to update --- smartlamp-kernel-module/test_driver.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/smartlamp-kernel-module/test_driver.c b/smartlamp-kernel-module/test_driver.c index 00ef6a9..978ef99 100644 --- a/smartlamp-kernel-module/test_driver.c +++ b/smartlamp-kernel-module/test_driver.c @@ -89,6 +89,15 @@ static ssize_t attr_store(struct kobject *sys_obj, struct kobj_attribute *attr, value = clamp_percent(value); (void)attr_name; + if(strcmp(attr_name,"ldr")) { + mock_ldr = value; + } + if(strcmp(attr_name,"led")) { + mock_led = value; + } + if(strcmp(attr_name,"threshold")) { + mock_threshold = value; + } // TASK 3.1: esta funcao e chamada quando o usuario escreve em um arquivo. // Exemplo: echo 75 | sudo tee /sys/kernel/smartlamp/ldr // From b3b0ef7c861f4e311ba6a20c237c9d320239e2a9 Mon Sep 17 00:00:00 2001 From: Vitor Aguiar Date: Tue, 12 May 2026 14:01:24 -0400 Subject: [PATCH 10/23] Revert "feat: added mock variables to driver mocking" This reverts commit 64fa6f1f735aeb233d729fac8151488ffe78c7bf. --- smartlamp-kernel-module/test_driver.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/smartlamp-kernel-module/test_driver.c b/smartlamp-kernel-module/test_driver.c index 978ef99..52000ee 100644 --- a/smartlamp-kernel-module/test_driver.c +++ b/smartlamp-kernel-module/test_driver.c @@ -14,10 +14,6 @@ static struct kobj_attribute led_attribute = __ATTR(led, 0664, attr_show, attr_s static struct kobj_attribute ldr_attribute = __ATTR(ldr, 0664, attr_show, attr_store); static struct kobj_attribute threshold_attribute = __ATTR(threshold, 0664, attr_show, attr_store); -static int mock_led = 0; -static int mock_ldr = 0; -static int mock_threshold = 0; - static struct attribute *attrs[] = { &led_attribute.attr, &ldr_attribute.attr, From 7ae87404a8f7965e376d16e54a3334a86659eaa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Vitor?= <¨vitoraguiar141@gmail.com¨> Date: Wed, 13 May 2026 20:33:44 -0400 Subject: [PATCH 11/23] Revert "refactor: added the proper target object for driver mock3.1" This reverts commit c969035b8d9f4b75110ab9d096e12064af58740d. --- smartlamp-kernel-module/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smartlamp-kernel-module/Makefile b/smartlamp-kernel-module/Makefile index 4408c31..23d5281 100644 --- a/smartlamp-kernel-module/Makefile +++ b/smartlamp-kernel-module/Makefile @@ -6,7 +6,7 @@ # Tarefa 2.3: obj-m += serial_read_2025.o # Tarefa 2.4: obj-m += sysfs_2025.o # Tarefa 3.1: obj-m += test_driver.o -obj-m += test_driver.o +obj-m += ALTERE_PARA_O_ARQUIVO_DA_TASK.o PWD := $(CURDIR) all: From e27fa128c8909fd4b9b273904cd5eb3ad91b805a Mon Sep 17 00:00:00 2001 From: Vitor Aguiar Date: Wed, 13 May 2026 11:24:01 -0400 Subject: [PATCH 12/23] feat: added feature to read integer from file --- daemon-2026-base/brightnessd_3_2.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/daemon-2026-base/brightnessd_3_2.c b/daemon-2026-base/brightnessd_3_2.c index 180c7d2..d21878a 100644 --- a/daemon-2026-base/brightnessd_3_2.c +++ b/daemon-2026-base/brightnessd_3_2.c @@ -33,6 +33,19 @@ static int read_int_file(const char *path, int *value) // Retorne 0 em caso de sucesso ou um codigo negativo em caso de erro. (void)path; (void)value; + + FILE *ftpr = fopen(path,"r"); + + if(ftpr == NULL) { + return -ENOSYS; + } + + int found = fscanf(ftpr,"%i",value); + + if(found > 0) { + return 0; + } + return -ENOSYS; } From 7b8330760431aa2d88294bcbb6764029bfc855b1 Mon Sep 17 00:00:00 2001 From: Vitor Aguiar Date: Wed, 13 May 2026 11:37:15 -0400 Subject: [PATCH 13/23] feat: added ldr to percent logic --- daemon-2026-base/brightnessd_3_2.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/daemon-2026-base/brightnessd_3_2.c b/daemon-2026-base/brightnessd_3_2.c index d21878a..808a1c3 100644 --- a/daemon-2026-base/brightnessd_3_2.c +++ b/daemon-2026-base/brightnessd_3_2.c @@ -53,7 +53,15 @@ static int ldr_to_percent(int ldr) { // TASK 3.2: limite o LDR para 0-100 e aplique um brilho minimo. (void)ldr; - return MIN_PERCENT; + if (ldr <= 0) { + ldr = MIN_PERCENT; + } + + if(ldr > 100) { + ldr = 100; + } + + return ldr; } static void sleep_ms(int milliseconds) From 428fd69b1030a2a8b41f9e3dc8f54e6629a9049b Mon Sep 17 00:00:00 2001 From: Vitor Aguiar Date: Fri, 15 May 2026 11:37:24 -0400 Subject: [PATCH 14/23] feat: added fclose --- daemon-2026-base/brightnessd_3_2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon-2026-base/brightnessd_3_2.c b/daemon-2026-base/brightnessd_3_2.c index 808a1c3..ab8e725 100644 --- a/daemon-2026-base/brightnessd_3_2.c +++ b/daemon-2026-base/brightnessd_3_2.c @@ -41,7 +41,7 @@ static int read_int_file(const char *path, int *value) } int found = fscanf(ftpr,"%i",value); - + fclose(ftpr); if(found > 0) { return 0; } From fd5dbcc999c3b4c79aa8be70ce423cc0d499b293 Mon Sep 17 00:00:00 2001 From: Vitor Aguiar Date: Fri, 15 May 2026 16:05:30 -0400 Subject: [PATCH 15/23] Revert "feat: added ldr to percent logic" This reverts commit 7b8330760431aa2d88294bcbb6764029bfc855b1. --- daemon-2026-base/brightnessd_3_2.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/daemon-2026-base/brightnessd_3_2.c b/daemon-2026-base/brightnessd_3_2.c index ab8e725..d8b65cd 100644 --- a/daemon-2026-base/brightnessd_3_2.c +++ b/daemon-2026-base/brightnessd_3_2.c @@ -53,15 +53,7 @@ static int ldr_to_percent(int ldr) { // TASK 3.2: limite o LDR para 0-100 e aplique um brilho minimo. (void)ldr; - if (ldr <= 0) { - ldr = MIN_PERCENT; - } - - if(ldr > 100) { - ldr = 100; - } - - return ldr; + return MIN_PERCENT; } static void sleep_ms(int milliseconds) From e239f245db2c8d2f2c6b24b93ddb66e062c38f2d Mon Sep 17 00:00:00 2001 From: Vitor Aguiar Date: Fri, 15 May 2026 16:26:35 -0400 Subject: [PATCH 16/23] feat: ldr to percent logic --- daemon-2026-base/brightnessd_3_2.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/daemon-2026-base/brightnessd_3_2.c b/daemon-2026-base/brightnessd_3_2.c index d8b65cd..9e03c1f 100644 --- a/daemon-2026-base/brightnessd_3_2.c +++ b/daemon-2026-base/brightnessd_3_2.c @@ -53,6 +53,15 @@ static int ldr_to_percent(int ldr) { // TASK 3.2: limite o LDR para 0-100 e aplique um brilho minimo. (void)ldr; + + if(ldr > MIN_PERCENT && ldr <= 100){ + return ldr; + } + + if(ldr > 100) { + return 100; + } + return MIN_PERCENT; } From ea68a446dffa2b387e2ad77e64616fffd13ab5ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Vitor?= <¨vitoraguiar141@gmail.com¨> Date: Fri, 15 May 2026 18:58:10 -0400 Subject: [PATCH 17/23] feat: added read_int_file logic --- daemon-2026-base/brightnessd_3_3.c | 40 ++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/daemon-2026-base/brightnessd_3_3.c b/daemon-2026-base/brightnessd_3_3.c index 7cc064f..4f4ac4e 100644 --- a/daemon-2026-base/brightnessd_3_3.c +++ b/daemon-2026-base/brightnessd_3_3.c @@ -14,7 +14,8 @@ static volatile sig_atomic_t running = 1; -struct config { +struct config +{ const char *ldr_path; const char *backlight_path; int interval_ms; @@ -40,6 +41,21 @@ static int read_int_file(const char *path, int *value) // TASK 3.3: reaproveite a implementacao da task 3.2. (void)path; (void)value; + + FILE *ftpr = fopen(path, "r"); + + if (ftpr == NULL) + { + return -ENOSYS; + } + + int found = fscanf(ftpr, "%i", value); + fclose(ftpr); + if (found > 0) + { + return 0; + } + return -ENOSYS; } @@ -71,7 +87,8 @@ static void sleep_ms(int milliseconds) request.tv_sec = milliseconds / 1000; request.tv_nsec = (long)(milliseconds % 1000) * 1000000L; - while (running && nanosleep(&request, &request) == -1 && errno == EINTR) { + while (running && nanosleep(&request, &request) == -1 && errno == EINTR) + { } } @@ -79,8 +96,10 @@ static int parse_args(int argc, char **argv, struct config *config) { int opt; - while ((opt = getopt(argc, argv, "l:b:i:h")) != -1) { - switch (opt) { + while ((opt = getopt(argc, argv, "l:b:i:h")) != -1) + { + switch (opt) + { case 'l': config->ldr_path = optarg; break; @@ -123,22 +142,27 @@ int main(int argc, char **argv) signal(SIGINT, handle_signal); signal(SIGTERM, handle_signal); - if (read_int_file(max_path, &max_brightness) < 0 || max_brightness <= 0) { + if (read_int_file(max_path, &max_brightness) < 0 || max_brightness <= 0) + { fprintf(stderr, "failed to read %s\n", max_path); return EXIT_FAILURE; } - while (running) { + while (running) + { int ldr; int brightness; - if (read_int_file(config.ldr_path, &ldr) == 0) { + if (read_int_file(config.ldr_path, &ldr) == 0) + { brightness = ldr_to_brightness(ldr, max_brightness); // TASK 3.3: escreva brightness em brightness_path usando write_int_file(). printf("ldr=%d brightness=%d max_brightness=%d\n", ldr, brightness, max_brightness); fflush(stdout); - } else { + } + else + { fprintf(stderr, "failed to read %s\n", config.ldr_path); } From cd16e0a3cc0da27de53b49707b40462a72aaddcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Vitor?= <¨vitoraguiar141@gmail.com¨> Date: Fri, 15 May 2026 19:04:58 -0400 Subject: [PATCH 18/23] feat: added write_int_file code --- daemon-2026-base/brightnessd_3_3.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/daemon-2026-base/brightnessd_3_3.c b/daemon-2026-base/brightnessd_3_3.c index 4f4ac4e..f05862a 100644 --- a/daemon-2026-base/brightnessd_3_3.c +++ b/daemon-2026-base/brightnessd_3_3.c @@ -65,6 +65,21 @@ static int __attribute__((unused)) write_int_file(const char *path, int value) // Use essa funcao para atualizar o brilho real da tela. (void)path; (void)value; + + FILE *ftpr = fopen(path, "r"); + + if (ftpr == NULL) + { + return -ENOSYS; + } + + int found = fprintf(ftpr, "%i", value); + fclose(ftpr); + if (found > 0) + { + return 0; + } + return -ENOSYS; } From 9d61d15e9deab650c7b50f52a3be1f4ac6759ab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Denis?= <¨denisguimaraes2012@gmail.com¨> Date: Fri, 15 May 2026 19:35:32 -0400 Subject: [PATCH 19/23] add esp32 vendor and product ID --- smartlamp-kernel-module/serial_read_2025.c | 57 +++++++++++++++++++--- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/smartlamp-kernel-module/serial_read_2025.c b/smartlamp-kernel-module/serial_read_2025.c index 7d64536..fcbb2a2 100644 --- a/smartlamp-kernel-module/serial_read_2025.c +++ b/smartlamp-kernel-module/serial_read_2025.c @@ -15,8 +15,9 @@ static uint usb_in, usb_out; // Endereços das portas de e static char *usb_in_buffer, *usb_out_buffer; // Buffers de entrada e saída da USB static int usb_max_size; // Tamanho máximo de uma mensagem USB -#define VENDOR_ID SUBSTITUA_PELO_VENDORID /* Encontre o VendorID do smartlamp */ -#define PRODUCT_ID SUBSTITUA_PELO_PRODUCTID /* Encontre o ProductID do smartlamp */ +#define VENDOR_ID 0x10c4 +#define PRODUCT_ID 0xea60 + static const struct usb_device_id id_table[] = { { USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, {} }; static int usb_probe(struct usb_interface *ifce, const struct usb_device_id *id); // Executado quando o dispositivo é conectado na USB @@ -101,10 +102,10 @@ static int usb_probe(struct usb_interface *interface, const struct usb_device_id // TASK 2.3: Leitura de dados periódicos enviados pelo firmware // O firmware envia RES GET_LDR Z automaticamente a cada 2 segundos // Descomente as linhas abaixo após implementar usb_read_serial - // ret = usb_read_serial(); - // if (ret >= 0) { - // printk(KERN_INFO "SmartLamp: Valor do LDR recebido: %d\n", ret); - // } + ret = usb_read_serial(); + if (ret >= 0) { + printk(KERN_INFO "SmartLamp: Valor do LDR recebido: %d\n", ret); + } return 0; } @@ -147,6 +148,7 @@ static int usb_read_serial(void) { int ret, actual_size; int recv_size = 0; // Quantidade de caracteres já recebidos em recv_line int i; + int value; printk(KERN_INFO "SmartLamp: Aguardando resposta do dispositivo...\n"); @@ -156,12 +158,53 @@ static int usb_read_serial(void) { // Você deve acumular os dados em recv_line até encontrar o caractere '\n' // // Dicas: - // - Use um loop para continuar lendo até encontrar '\n' + // - Use um loop para continuar lendo até encontrar '\n' (ok) // - Use usb_bulk_msg com usb_rcvbulkpipe para cada leitura // - Copie os dados de usb_in_buffer para recv_line // - Cuidado com buffer overflow: verifique recv_size < MAX_RECV_LINE // - Defina um timeout adequado (ex: 2000ms) // - Após receber a linha completa, extraia o valor numérico com sscanf + while(1){ + ret = usb_bulk_msg( + smartlamp_device, + usb_rcvbulkpipe(smartlamp_device, usb_in), + usb_in_buffer, + MAX_RECV_LINE, + &actual_size, + 2500 + ); + + if (ret) { + printk(KERN_ERR "SmartLamp: Erro na leitura USB (%d)\n", ret); + return ret; + } + + for (i = 0; i < actual_size; i++) { + + if (recv_size >= MAX_RECV_LINE - 1) { + printk(KERN_ERR "SmartLamp: Buffer overflow\n"); + return -1; + } + + recv_line[recv_size++] = usb_in_buffer[i]; + + if (usb_in_buffer[i] == '\n') { + + recv_line[recv_size] = '\0'; + + printk(KERN_INFO "SmartLamp: Linha recebida: %s\n", recv_line); + + if (sscanf(recv_line, "%d", &value) == 1) { + return value; + } + + printk(KERN_ERR "SmartLamp: Erro ao converter valor\n"); + return -1; + } + } + } + return -1; } + From 29fa58b156d536ca91197c0b7f1cd30645866639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Denis?= <¨denisguimaraes2012@gmail.com¨> Date: Fri, 15 May 2026 19:48:02 -0400 Subject: [PATCH 20/23] implement serial_read function --- smartlamp-kernel-module/serial_read_2025.c | 76 +++++++++------------- 1 file changed, 29 insertions(+), 47 deletions(-) diff --git a/smartlamp-kernel-module/serial_read_2025.c b/smartlamp-kernel-module/serial_read_2025.c index fcbb2a2..8020f95 100644 --- a/smartlamp-kernel-module/serial_read_2025.c +++ b/smartlamp-kernel-module/serial_read_2025.c @@ -29,7 +29,7 @@ static int usb_read_serial(void); static int smartlamp_config_serial(struct usb_device *dev) { int ret; - u32 baudrate = 9600; // Defina o baud rate que seu ESP32 usa! + u32 baudrate = 115200; // Defina o baud rate que seu ESP32 usa! printk(KERN_INFO "SmartLamp: Configurando a porta serial...\n"); @@ -140,71 +140,53 @@ static int usb_write_serial(char *cmd, int param) { return 0; } -// Lê uma linha completa da porta serial (até encontrar '\n') -// Retorna o valor numérico da resposta ou -1 em caso de erro -// Exemplo de resposta: "RES GET_LDR 450\n" -> retorna 450 -// Exemplo de resposta: "RES SET_LED 1\n" -> retorna 1 static int usb_read_serial(void) { int ret, actual_size; - int recv_size = 0; // Quantidade de caracteres já recebidos em recv_line + int recv_size = 0; int i; int value; printk(KERN_INFO "SmartLamp: Aguardando resposta do dispositivo...\n"); - // TASK 2.3: Implemente a leitura de dados da porta serial - // - // IMPORTANTE: Os dados podem chegar fragmentados (byte a byte ou em blocos) - // Você deve acumular os dados em recv_line até encontrar o caractere '\n' - // - // Dicas: - // - Use um loop para continuar lendo até encontrar '\n' (ok) - // - Use usb_bulk_msg com usb_rcvbulkpipe para cada leitura - // - Copie os dados de usb_in_buffer para recv_line - // - Cuidado com buffer overflow: verifique recv_size < MAX_RECV_LINE - // - Defina um timeout adequado (ex: 2000ms) - // - Após receber a linha completa, extraia o valor numérico com sscanf - - while(1){ - ret = usb_bulk_msg( - smartlamp_device, - usb_rcvbulkpipe(smartlamp_device, usb_in), - usb_in_buffer, - MAX_RECV_LINE, - &actual_size, - 2500 - ); - - if (ret) { - printk(KERN_ERR "SmartLamp: Erro na leitura USB (%d)\n", ret); - return ret; - } + ret = usb_bulk_msg( + smartlamp_device, + usb_rcvbulkpipe(smartlamp_device, usb_in), + usb_in_buffer, + usb_max_size, + &actual_size, + 2500 + ); - for (i = 0; i < actual_size; i++) { + if (ret) { + printk(KERN_ERR "SmartLamp: Erro na leitura USB (%d)\n", ret); + return ret; + } - if (recv_size >= MAX_RECV_LINE - 1) { - printk(KERN_ERR "SmartLamp: Buffer overflow\n"); - return -1; - } + for (i = 0; i < actual_size; i++) { - recv_line[recv_size++] = usb_in_buffer[i]; + if (recv_size >= MAX_RECV_LINE - 1) { + printk(KERN_ERR "SmartLamp: Buffer overflow\n"); + return -1; + } - if (usb_in_buffer[i] == '\n') { + recv_line[recv_size++] = usb_in_buffer[i]; - recv_line[recv_size] = '\0'; + if (usb_in_buffer[i] == '\n') { - printk(KERN_INFO "SmartLamp: Linha recebida: %s\n", recv_line); + recv_line[recv_size] = '\0'; - if (sscanf(recv_line, "%d", &value) == 1) { - return value; - } + printk(KERN_INFO "SmartLamp: Linha recebida: %s\n", recv_line); - printk(KERN_ERR "SmartLamp: Erro ao converter valor\n"); - return -1; + if (sscanf(recv_line, "GET_LDR %d", &value) == 1) { + return value; } + + printk(KERN_ERR "SmartLamp: Erro ao converter valor\n"); + return -1; } } + printk(KERN_ERR "SmartLamp: Linha incompleta\n"); return -1; } From 56b92ea005fe02bb5fa19db57882480691f8fd62 Mon Sep 17 00:00:00 2001 From: mello Date: Fri, 15 May 2026 19:53:20 -0400 Subject: [PATCH 21/23] firmware 1.4 --- esp32/src/main.cpp | 142 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 128 insertions(+), 14 deletions(-) diff --git a/esp32/src/main.cpp b/esp32/src/main.cpp index 429f563..6457085 100644 --- a/esp32/src/main.cpp +++ b/esp32/src/main.cpp @@ -1,29 +1,143 @@ #include +// Constants const int baudrate = 115200; -const int ledPin = 13; -const int ldrPin = 36; +const int ledPin = 4; +const int ldrPin = 34; +const float min_percentage = 0.0; +const float max_percentage = 100.0; +const float resolution = 4095.0; +const int channel = 0; +const int freq = 5000; +const int resolution_pwm = 8; +// Global variables +int threshold = 0; +int currentLedPct = 0; + +// Function headers +void print_ldr(void); +void automatic_led(void); +void get_threshold(void); +void error_command(void); +void set_threshold(String input); +void get_ldr(void); +void get_led(void); +void set_led(String input); +void setLedPercent(int pct); + +// Setup Arduino Framework void setup() { Serial.begin(baudrate); - // Serial.println("Hello World!"); - Serial.println("Write something: "); - pinMode(ledPin, OUTPUT); + Serial.println("Ping! I'm alive!"); + ledcSetup(channel, freq, resolution_pwm); + ledcAttachPin(ledPin, channel); pinMode(ldrPin, INPUT); } +// Loop Arduino Framework void loop() { - if (Serial.available() > 0) { - String input = Serial.readString(); - Serial.println("You wrote: " + input); + if (Serial.available()) { + String input = Serial.readStringUntil('\n'); + input.replace("\r", ""); + input.trim(); + if (input.length() == 0) return; // ignore trash + if (input.startsWith("SET_LED ")) set_led(input); + else if (input.startsWith("GET_LED")) get_led(); + else if (input.startsWith("GET_LDR")) get_ldr(); + else if (input.startsWith("SET_THRESHOLD ")) set_threshold(input); + else if (input.startsWith("GET_THRESHOLD")) get_threshold(); + else error_command(); + } + + automatic_led(); + print_ldr(); + delay(2000); +} + +void print_ldr(void) { + int ldr_pwm = analogRead(ldrPin); + float ldr_pct = (ldr_pwm * max_percentage) / resolution; + Serial.println("GET_LDR " + String(int(ldr_pct))); +} + +void automatic_led(void) { + + int ldr = analogRead(ldrPin); + float ldr_pct = (ldr * max_percentage) / resolution; + if (ldr_pct > threshold) { + setLedPercent(currentLedPct); + } else { + setLedPercent(0); } +} + +void get_threshold(void) { + /* + Retorna o valor atual do threshold. + */ + + Serial.println("RES GET_THRESHOLD " + String(threshold)); +} + +void error_command(void) { + Serial.println("ERR Unknown command."); +} + +void set_threshold(String input) { + /* + Define o limiar de ativação automática do LED (X entre 0-100). + O LED acende automaticamente quando a leitura normalizada do LDR + ultrapassar esse valor. + */ - // digitalWrite(ledPin, HIGH); - // delay(1000); - // digitalWrite(ledPin, LOW); - delay(100); + String threshold_str = input.substring(14); + threshold = threshold_str.toInt(); + Serial.println("RES SET_THRESHOLD 1"); +} + +void get_ldr(void) { + /* + Retorna o valor da leitura atual do LDR + (normalizado entre 0-100) + */ + + int ldrValue = analogRead(ldrPin); + float percentage = (ldrValue * max_percentage) / resolution; + Serial.println("RES GET_LDR " + String(int(percentage))); +} + +void get_led(void) { + /* + Retorna a intensidade atual do LED. + */ + + Serial.println("RES GET_LED " + String(currentLedPct)); +} - int value = analogRead(ldrPin); - Serial.println(value); +void set_led(String input) { + /* + Define a intensidade do LED (X entre 0-100). Valores fora + desse intervalo devem ser ignorados e retornar erro. + */ + + String valueStr = input.substring(8); + int luminosity = valueStr.toInt(); + + + if (luminosity >= min_percentage && luminosity <= max_percentage) { + + currentLedPct = luminosity; + setLedPercent(luminosity); + + Serial.println("RES SET_LED 1"); + } + else { + Serial.println("RES SET_LED -1"); + } +} +void setLedPercent(int pct) { + int duty = (pct * 255) / 100; + ledcWrite(channel, duty); } \ No newline at end of file From 76643ac746190e8fe5ad057d2175efdee47d6921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Vitor?= <¨vitoraguiar141@gmail.com¨> Date: Fri, 15 May 2026 19:58:28 -0400 Subject: [PATCH 22/23] feat:added brightness logic --- daemon-2026-base/brightnessd_3_3.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/daemon-2026-base/brightnessd_3_3.c b/daemon-2026-base/brightnessd_3_3.c index f05862a..0bf603c 100644 --- a/daemon-2026-base/brightnessd_3_3.c +++ b/daemon-2026-base/brightnessd_3_3.c @@ -66,7 +66,7 @@ static int __attribute__((unused)) write_int_file(const char *path, int value) (void)path; (void)value; - FILE *ftpr = fopen(path, "r"); + FILE *ftpr = fopen(path, "w"); if (ftpr == NULL) { @@ -74,6 +74,7 @@ static int __attribute__((unused)) write_int_file(const char *path, int value) } int found = fprintf(ftpr, "%i", value); + fclose(ftpr); if (found > 0) { @@ -92,6 +93,14 @@ static int ldr_to_brightness(int ldr, int max_brightness) percent = MIN_PERCENT; (void)ldr; (void)max_brightness; + int comparison = ldr * (max_brightness / 100); + + if (comparison < percent) + { + return percent; + } + percent = comparison; + return percent; } @@ -173,6 +182,10 @@ int main(int argc, char **argv) brightness = ldr_to_brightness(ldr, max_brightness); // TASK 3.3: escreva brightness em brightness_path usando write_int_file(). + if (write_int_file(brightness_path, brightness) != 0) + { + return EXIT_FAILURE; + } printf("ldr=%d brightness=%d max_brightness=%d\n", ldr, brightness, max_brightness); fflush(stdout); } From 88555f4e20b5ff06eb67ebb4743c156538d43c60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Denis?= <¨denisguimaraes2012@gmail.com¨> Date: Fri, 15 May 2026 20:42:38 -0400 Subject: [PATCH 23/23] implement serial_read function --- smartlamp-kernel-module/sysfs_2025.c | 251 ++++++++++++++------------- 1 file changed, 132 insertions(+), 119 deletions(-) diff --git a/smartlamp-kernel-module/sysfs_2025.c b/smartlamp-kernel-module/sysfs_2025.c index 47a0ea9..9a4fac1 100644 --- a/smartlamp-kernel-module/sysfs_2025.c +++ b/smartlamp-kernel-module/sysfs_2025.c @@ -10,28 +10,23 @@ MODULE_LICENSE("GPL"); static char recv_line[MAX_RECV_LINE]; // Buffer para armazenar linha completa recebida static struct usb_device *smartlamp_device; // Referência para o dispositivo USB -static uint usb_in, usb_out; // Endereços das portas de entrada e saida da USB +static uint usb_in, usb_out; // Endereços das portas de entrada e saída da USB static char *usb_in_buffer, *usb_out_buffer; // Buffers de entrada e saída da USB static int usb_max_size; // Tamanho máximo de uma mensagem USB -#define VENDOR_ID SUBSTITUA_PELO_VENDORID /* Encontre o VendorID do smartlamp */ -#define PRODUCT_ID SUBSTITUA_PELO_PRODUCTID /* Encontre o ProductID do smartlamp */ +#define VENDOR_ID 0x10c4 +#define PRODUCT_ID 0xea60 + static const struct usb_device_id id_table[] = { { USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, {} }; -static int usb_probe(struct usb_interface *ifce, const struct usb_device_id *id); // Executado quando o dispositivo é conectado na USB -static void usb_disconnect(struct usb_interface *ifce); // Executado quando o dispositivo USB é desconectado da USB -static int usb_write_serial(char *cmd, int param); // Executado para enviar um comando para o dispositivo -static int usb_read_serial(char *cmd); // Executado para ler a resposta esperada da porta serial +static int usb_probe(struct usb_interface *ifce, const struct usb_device_id *id); +static void usb_disconnect(struct usb_interface *ifce); +static int usb_write_serial(char *cmd, int param); +static int usb_read_serial(char *cmd); -// Executado quando o arquivo /sys/kernel/smartlamp/{led, ldr, threshold} é lido -// Exemplo: cat /sys/kernel/smartlamp/led static ssize_t attr_show(struct kobject *sys_obj, struct kobj_attribute *attr, char *buff); - -// Executado quando o arquivo /sys/kernel/smartlamp/{led, ldr, threshold} é escrito -// Exemplo: echo "100" | sudo tee /sys/kernel/smartlamp/led static ssize_t attr_store(struct kobject *sys_obj, struct kobj_attribute *attr, const char *buff, size_t count); -// Variáveis para criar os arquivos em /sys/kernel/smartlamp/{led, ldr, threshold} static struct kobj_attribute led_attribute = __ATTR(led, S_IRUGO | S_IWUSR, attr_show, attr_store); static struct kobj_attribute ldr_attribute = __ATTR(ldr, S_IRUGO | S_IWUSR, attr_show, attr_store); static struct kobj_attribute threshold_attribute = __ATTR(threshold, S_IRUGO | S_IWUSR, attr_show, attr_store); @@ -39,34 +34,23 @@ static struct attribute *attrs[] = { &led_attribute.attr, &ldr_ static struct attribute_group attr_group = { .attrs = attrs }; static struct kobject *sys_obj; -// Função para configurar os parâmetros seriais do CP2102 via Control-Messages static int smartlamp_config_serial(struct usb_device *dev) { int ret; - u32 baudrate = 9600; // Defina o baud rate que seu ESP32 usa! + u32 baudrate = 115200; printk(KERN_INFO "SmartLamp: Configurando a porta serial...\n"); - // 1. Habilita a interface UART do CP2102 - // Comando específico do vendor Silicon Labs (CP210X_IFC_ENABLE) - // bmRequestType: 0x41 (Vendor, Host-to-Device, Interface) - // bRequest: 0x00 (CP210X_IFC_ENABLE) - // wValue: 0x0001 (UART Enable) ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x00, 0x41, 0x0001, 0, NULL, 0, 1000); - if (ret) - { + if (ret) { printk(KERN_ERR "SmartLamp: Erro ao habilitar a UART (código %d)\n", ret); return ret; } - // 2. Define o baud rate - // Comando específico do vendor Silicon Labs (CP210X_SET_BAUDRATE) - // bRequest: 0x1E (CP210X_SET_BAUDRATE) ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x1E, 0x41, 0, 0, &baudrate, sizeof(baudrate), 1000); - if (ret < 0) - { + if (ret < 0) { printk(KERN_ERR "SmartLamp: Erro ao configurar o baud rate (código %d)\n", ret); return ret; } @@ -76,44 +60,38 @@ static int smartlamp_config_serial(struct usb_device *dev) } MODULE_DEVICE_TABLE(usb, id_table); -bool ignore = true; static struct usb_driver smartlamp_driver = { - .name = "smartlamp", // Nome do driver - .probe = usb_probe, // Executado quando o dispositivo é conectado na USB - .disconnect = usb_disconnect, // Executado quando o dispositivo é desconectado na USB - .id_table = id_table, // Tabela com o VendorID e ProductID do dispositivo + .name = "smartlamp", + .probe = usb_probe, + .disconnect = usb_disconnect, + .id_table = id_table, }; module_usb_driver(smartlamp_driver); -// Executado quando o dispositivo é conectado na USB static int usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct usb_endpoint_descriptor *usb_endpoint_in, *usb_endpoint_out; int ret; printk(KERN_INFO "SmartLamp: Dispositivo conectado ...\n"); - // Detecta portas e aloca buffers de entrada e saída de dados na USB smartlamp_device = interface_to_usbdev(interface); - ignore = usb_find_common_endpoints(interface->cur_altsetting, &usb_endpoint_in, &usb_endpoint_out, NULL, NULL); + usb_find_common_endpoints(interface->cur_altsetting, &usb_endpoint_in, &usb_endpoint_out, NULL, NULL); usb_max_size = usb_endpoint_maxp(usb_endpoint_in); usb_in = usb_endpoint_in->bEndpointAddress; usb_out = usb_endpoint_out->bEndpointAddress; usb_in_buffer = kmalloc(usb_max_size, GFP_KERNEL); usb_out_buffer = kmalloc(usb_max_size, GFP_KERNEL); - // Chama a função para configurar a porta serial antes de usar ret = smartlamp_config_serial(smartlamp_device); - if (ret) - { + if (ret) { printk(KERN_ERR "SmartLamp: Falha na configuração da serial\n"); kfree(usb_in_buffer); kfree(usb_out_buffer); return ret; } - // Cria os arquivos /sys/kernel/smartlamp/led, /sys/kernel/smartlamp/ldr e /sys/kernel/smartlamp/threshold sys_obj = kobject_create_and_add("smartlamp", kernel_kobj); if (!sys_obj) { kfree(usb_in_buffer); @@ -133,7 +111,6 @@ static int usb_probe(struct usb_interface *interface, const struct usb_device_id return 0; } -// Executado quando o dispositivo USB é desconectado da USB static void usb_disconnect(struct usb_interface *interface) { printk(KERN_INFO "SmartLamp: Dispositivo desconectado.\n"); @@ -142,121 +119,157 @@ static void usb_disconnect(struct usb_interface *interface) { kobject_put(sys_obj); } - kfree(usb_in_buffer); // Desaloca buffers + kfree(usb_in_buffer); kfree(usb_out_buffer); } -// Envia um comando para o dispositivo USB. -// Esta função deve reaproveitar a implementação feita na Tarefa 2.2. -// Em sysfs_2025.c, param >= 0 indica comando com parâmetro (ex: SET_LED 80) -// e param < 0 indica comando sem parâmetro (ex: GET_LDR). -// Exemplos de uso: -// - usb_write_serial("SET_LED", 80) deve enviar "SET_LED 80\n" -// - usb_write_serial("GET_LDR", -1) deve enviar "GET_LDR\n" static int usb_write_serial(char *cmd, int param) { int ret, actual_size; - printk(KERN_INFO "SmartLamp: Enviando comando: %s %d\n", cmd, param); + if (param >= 0) + sprintf(usb_out_buffer, "%s %d\n", cmd, param); + else + sprintf(usb_out_buffer, "%s\n", cmd); + + printk(KERN_INFO "SmartLamp: Enviando comando: %s", usb_out_buffer); - // TASK 2.4: adapte aqui a solução da Tarefa 2.2. - // Dica: quando param for negativo, envie apenas "COMANDO\n". - // Quando param for 0 ou maior, envie "COMANDO PARAMETRO\n". - // Depois, envie o buffer pela USB usando usb_bulk_msg. + ret = usb_bulk_msg( + smartlamp_device, + usb_sndbulkpipe(smartlamp_device, usb_out), + usb_out_buffer, + strlen(usb_out_buffer), + &actual_size, + 1000 + ); + + if (ret) { + printk(KERN_ERR "SmartLamp: Erro de codigo %d ao enviar comando!\n", ret); + return -1; + } return 0; } -// Lê respostas da porta serial até encontrar uma resposta para o comando esperado. -// Esta função deve reaproveitar a implementação feita na Tarefa 2.3. -// O parâmetro cmd indica qual resposta deve ser aceita. -// Exemplos: -// - usb_read_serial("GET_LDR") deve aceitar "RES GET_LDR 45\n" e retornar 45. -// - usb_read_serial("SET_LED") deve aceitar "RES SET_LED 1\n" e retornar 1. -// Mensagens de outros comandos devem ser ignoradas. -static int usb_read_serial(char *cmd) { +static int usb_read_serial(char *cmd) +{ int ret, actual_size; - int recv_size = 0; // Quantidade de caracteres já recebidos em recv_line + int recv_size = 0; int i; + int value; + + printk(KERN_INFO "SmartLamp: Aguardando resposta do dispositivo...\n"); + + ret = usb_bulk_msg( + smartlamp_device, + usb_rcvbulkpipe(smartlamp_device, usb_in), + usb_in_buffer, + usb_max_size, + &actual_size, + 2500 + ); - printk(KERN_INFO "SmartLamp: Aguardando resposta para %s...\n", cmd); - - // TASK 2.4: adapte aqui a solução da Tarefa 2.3. - // - // IMPORTANTE: Os dados podem chegar fragmentados (byte a byte ou em blocos) - // Você deve acumular os dados em recv_line até encontrar o caractere '\n' - // e processar apenas linhas que comecem com "RES ". - // - // Dicas: - // - Use um loop para continuar lendo até encontrar '\n' - // - Use usb_bulk_msg com usb_rcvbulkpipe para cada leitura - // - Copie os dados de usb_in_buffer para recv_line - // - Cuidado com buffer overflow: verifique recv_size < MAX_RECV_LINE - // - Defina um timeout adequado (ex: 2000ms) - // - Ignore linhas que não correspondem ao comando esperado - // - Após receber a linha correta, extraia o valor numérico e retorne + if (ret) { + printk(KERN_ERR "SmartLamp: Erro na leitura USB (%d)\n", ret); + return ret; + } + + for (i = 0; i < actual_size; i++) { + if (recv_size >= MAX_RECV_LINE - 1) { + printk(KERN_ERR "SmartLamp: Buffer overflow\n"); + return -1; + } + + recv_line[recv_size++] = usb_in_buffer[i]; + + if (usb_in_buffer[i] == '\n') { + recv_line[recv_size] = '\0'; + printk(KERN_INFO "SmartLamp: Linha recebida: %s\n", recv_line); + + if (strcmp(cmd, "GET_LDR") == 0) { + if (sscanf(recv_line, "GET_LDR %d", &value) == 1) + return value; + } else if (strcmp(cmd, "GET_LED") == 0) { + if (sscanf(recv_line, "GET_LED %d", &value) == 1) + return value; + } else if (strcmp(cmd, "GET_THRESHOLD") == 0) { + if (sscanf(recv_line, "GET_THRESHOLD %d", &value) == 1) + return value; + } else if (strcmp(cmd, "SET_LED") == 0) { + if (sscanf(recv_line, "SET_LED %d", &value) == 1) + return value; + } else if (strcmp(cmd, "SET_THRESHOLD") == 0) { + if (sscanf(recv_line, "SET_THRESHOLD %d", &value) == 1) + return value; + } else { + printk(KERN_ERR "SmartLamp: comando desconhecido: %s\n", cmd); + return -1; + } + + printk(KERN_ERR "SmartLamp: Erro ao converter valor\n"); + return -1; + } + } return -1; } - -// Executado quando algum arquivo em /sys/kernel/smartlamp/{led, ldr, threshold} é lido. -// Parâmetros: -// - sys_obj: objeto do kernel que representa o diretório /sys/kernel/smartlamp. -// - attr: atributo que representa o arquivo acessado (led, ldr ou threshold). -// - buff: buffer onde a função deve escrever o texto que será retornado para o usuário. -// Retorno: quantidade de bytes escritos em buff. -static ssize_t attr_show(struct kobject *sys_obj, struct kobj_attribute *attr, char *buff) { +static ssize_t attr_show(struct kobject *sys_obj, struct kobj_attribute *attr, char *buff) +{ int value = -1; - // attr_name guarda o nome do arquivo sysfs acessado. - // Exemplos: "led" quando o usuário roda cat /sys/kernel/smartlamp/led, - // "ldr" quando lê /sys/kernel/smartlamp/ldr e "threshold" para threshold. const char *attr_name = attr->attr.name; printk(KERN_INFO "SmartLamp: Lendo %s ...\n", attr_name); - // TASK 2.4: implemente a leitura via sysfs. - // Use attr_name para identificar se o usuario leu led, ldr ou threshold. - // Para cada arquivo, envie o comando GET correspondente ao firmware - // e use usb_read_serial("GET_...") para obter o valor retornado em buff. + if (strcmp(attr_name, "led") == 0) { + usb_write_serial("GET_LED", -1); + value = usb_read_serial("GET_LED"); + } else if (strcmp(attr_name, "ldr") == 0) { + usb_write_serial("GET_LDR", -1); + value = usb_read_serial("GET_LDR"); + } else if (strcmp(attr_name, "threshold") == 0) { + usb_write_serial("GET_THRESHOLD", -1); + value = usb_read_serial("GET_THRESHOLD"); + } else { + printk(KERN_ERR "SmartLamp: atributo inválido: %s\n", attr_name); + return -EINVAL; + } + + if (value < 0) { + printk(KERN_ERR "SmartLamp: erro ao ler %s\n", attr_name); + return -EIO; + } - sprintf(buff, "%d\n", value); - return strlen(buff); + return sprintf(buff, "%d\n", value); } -// Executado quando algum arquivo em /sys/kernel/smartlamp/{led, ldr, threshold} recebe escrita. -// Exemplo: echo 100 | sudo tee /sys/kernel/smartlamp/led -// Parâmetros: -// - sys_obj: objeto do kernel que representa o diretório /sys/kernel/smartlamp. -// - attr: atributo que representa o arquivo escrito (led, ldr ou threshold). -// - buff: buffer com o texto enviado pelo usuário. -// - count: quantidade de bytes recebidos em buff. -// Retorno: quantidade de bytes processados ou código de erro negativo. -static ssize_t attr_store(struct kobject *sys_obj, struct kobj_attribute *attr, const char *buff, size_t count) { +static ssize_t attr_store(struct kobject *sys_obj, struct kobj_attribute *attr, const char *buff, size_t count) +{ long ret, value; - // attr_name guarda o nome do arquivo sysfs que recebeu a escrita. - // Use esse valor para decidir se o comando será SET_LED, SET_THRESHOLD - // ou se a operação deve ser recusada porque ldr é somente leitura. const char *attr_name = attr->attr.name; ret = kstrtol(buff, 10, &value); if (ret) { printk(KERN_ALERT "SmartLamp: valor de %s invalido.\n", attr_name); - return -EACCES; + return -EINVAL; } printk(KERN_INFO "SmartLamp: Setando %s para %ld ...\n", attr_name, value); - // TASK 2.4: implemente a escrita via sysfs. - // Use attr_name para permitir escrita em led e threshold. - // Para led, envie SET_LED com o valor recebido. - // Para threshold, envie SET_THRESHOLD com o valor recebido. - // Depois de enviar, leia a resposta do firmware com usb_read_serial("SET_..."). - // O arquivo ldr representa o sensor de luz e deve ser somente leitura. - - if (ret < 0) { - printk(KERN_ALERT "SmartLamp: erro ao setar o valor do %s.\n", attr_name); + if (strcmp(attr_name, "ldr") == 0) { + printk(KERN_ERR "SmartLamp: ldr é somente leitura\n"); return -EACCES; } - return strlen(buff); -} + if (strcmp(attr_name, "led") == 0) { + usb_write_serial("SET_LED", value); + usb_read_serial("SET_LED"); + } else if (strcmp(attr_name, "threshold") == 0) { + usb_write_serial("SET_THRESHOLD", value); + usb_read_serial("SET_THRESHOLD"); + } else { + printk(KERN_ERR "SmartLamp: atributo inválido: %s\n", attr_name); + return -EINVAL; + } + + return count; +} \ No newline at end of file