2 * device-manager-plugin-rpi3
4 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
24 #include "../shared.h"
26 #include <peripheral_io.h>
28 #define GET_BRIGHTNESS(val) (((val) >> 24) & 0xFF)
30 #define GET_TYPE(a) (((a) >> 24) & 0xFF)
31 #define GET_RED_ONLY(a) ((a) & 0xFF0000)
32 #define GET_GREEN_ONLY(a) ((a) & 0x00FF00)
33 #define GET_BLUE_ONLY(a) ((a) & 0x0000FF)
34 #define GET_RED_BRT(a) (uint8_t)(((a) >> 16) & 0xFF)
35 #define GET_GREEN_BRT(a) (uint8_t)(((a) >> 8) & 0xFF)
36 #define GET_BLUE_BRT(a) (uint8_t)((a) & 0xFF)
41 #define GPIO_I2C_BUS_INDEX 1
42 #define BLINKM_DEFAULT_ADDR 0x09
45 * LED operation command code
46 * Stop script: 0x6f('o')
47 * Set command: 0x6e('n')
48 * Change address command: 0x41('A')
50 #define SET_CMD_CODE 0x6e
51 #define STOP_SCRIPT_CMD 0x6f
52 #define CHANGE_ADDR_CMD 0x41
54 typedef enum _led_rgb_type {
60 struct gpio_rgb_play_color_info {
65 struct gpio_rgb_play_info {
72 static uint8_t off_cmd[4] = { SET_CMD_CODE, 0x00, 0x00, 0x00 };
74 static void blinkm_led_stop_script(peripheral_i2c_h handle)
76 uint8_t data[1] = {STOP_SCRIPT_CMD};
79 peripheral_i2c_write(handle, data, length);
85 static void blinkm_led_off(peripheral_i2c_h handle)
87 peripheral_i2c_write(handle, off_cmd, sizeof(off_cmd));
90 static void blinkm_led_init(peripheral_i2c_h handle)
92 blinkm_led_stop_script(handle);
93 blinkm_led_off(handle);
96 static void blinkm_led_set_color(peripheral_i2c_h handle, uint8_t *pkt_data, int len)
98 peripheral_i2c_write(handle, pkt_data, len);
101 static int gpio_led_open_device(int device_index, peripheral_i2c_h *device_handle)
105 if ((ret = peripheral_i2c_open(device_index, BLINKM_DEFAULT_ADDR, device_handle)) < PERIPHERAL_ERROR_NONE) {
106 _E("Failed to open I2C");
111 static int gpio_led_close_device(peripheral_i2c_h device_handle)
115 if ((ret = peripheral_i2c_close(device_handle)) < PERIPHERAL_ERROR_NONE) {
116 _E("Failed to close I2C");
121 static int gpio_rgb_set_brightness(struct led_state *state)
123 uint8_t cmd_pkt[4] = { SET_CMD_CODE, };
124 peripheral_i2c_h handle;
131 color = state->color;
133 cmd_pkt[1] = GET_RED_BRT(color);
134 cmd_pkt[2] = GET_GREEN_BRT(color);
135 cmd_pkt[3] = GET_BLUE_BRT(color);
137 _I("COLOR(%x) r(%x), g(%x), b(%x)", color, cmd_pkt[1], cmd_pkt[2], cmd_pkt[3]);
139 if ((ret = gpio_led_open_device(GPIO_I2C_BUS_INDEX, &handle)) < PERIPHERAL_ERROR_NONE)
142 blinkm_led_set_color(handle, cmd_pkt, sizeof(cmd_pkt));
144 if ((ret = gpio_led_close_device(handle)) < PERIPHERAL_ERROR_NONE)
151 static int gpio_rgb_turn_off(struct led_state *state)
153 struct led_state st = { LED_TYPE_MANUAL, };
154 return gpio_rgb_set_brightness(&st);
157 /* release play list */
158 static void free_func(gpointer data)
160 struct gpio_rgb_play_color_info *color = data;
164 static void release_play_info(void)
166 if (play_info.play_list) {
167 g_list_free_full(play_info.play_list, free_func);
168 play_info.play_list = NULL;
170 play_info.nr_play = 0;
172 if (play_info.timer) {
173 g_source_remove(play_info.timer);
177 gpio_rgb_turn_off(NULL);
180 static int gpio_rgb_init_led()
182 peripheral_i2c_h handle;
185 if ((ret = gpio_led_open_device(GPIO_I2C_BUS_INDEX, &handle)) < PERIPHERAL_ERROR_NONE)
188 blinkm_led_init(handle);
190 if ((ret = gpio_led_close_device(handle)) < PERIPHERAL_ERROR_NONE)
196 /* timer callback to change colors which are stored in play_list */
197 static gboolean gpio_rgb_timer_expired(gpointer data)
199 struct gpio_rgb_play_color_info *color;
200 struct led_state state = {LED_TYPE_MANUAL, };
203 if (play_info.timer) {
204 g_source_remove(play_info.timer);
208 color = g_list_nth_data(play_info.play_list, play_info.index);
210 _E("Failed to get (%d)th item from the play list", play_info.index);
214 play_info.timer = g_timeout_add(color->time, gpio_rgb_timer_expired, data);
215 if (play_info.timer == 0) {
216 _E("Failed to add timeout for LED blinking");
220 state.color = color->color;
222 ret = gpio_rgb_set_brightness(&state);
224 _E("Failed to set brightness (%d)", ret);
229 if (play_info.index == play_info.nr_play)
232 return G_SOURCE_CONTINUE;
237 return G_SOURCE_REMOVE;
240 /* insert color info to the play_list */
241 static int gpio_rgb_insert_play_list(unsigned color, int on, int off)
243 struct gpio_rgb_play_color_info *on_info, *off_info;
247 on_info = calloc(1, sizeof(struct gpio_rgb_play_color_info));
250 off_info = calloc(1, sizeof(struct gpio_rgb_play_color_info));
256 on_info->color = color;
258 play_info.play_list = g_list_append(play_info.play_list, on_info);
261 off_info->time = off;
262 play_info.play_list = g_list_append(play_info.play_list, off_info);
267 /* insert color info to the play list and start to play */
268 static int gpio_rgb_set_brightness_blink(struct led_state *state)
273 val = GET_RED_ONLY(state->color);
275 ret = gpio_rgb_insert_play_list(val, state->duty_on, state->duty_off);
277 _E("Failed to insert color info to list (%d)", ret);
279 val = GET_GREEN_ONLY(state->color);
281 ret = gpio_rgb_insert_play_list(val, state->duty_on, state->duty_off);
283 _E("Failed to insert color info to list (%d)", ret);
285 val = GET_BLUE_ONLY(state->color);
287 ret = gpio_rgb_insert_play_list(val, state->duty_on, state->duty_off);
289 _E("Failed to insert color info to list (%d)", ret);
292 play_info.nr_play = g_list_length(play_info.play_list);
295 gpio_rgb_timer_expired(NULL);
299 static int gpio_rgb_turn_on(struct led_state *state)
301 if (state->type == LED_TYPE_MANUAL)
302 return gpio_rgb_set_brightness(state);
304 return gpio_rgb_set_brightness_blink(state);
307 static int gpio_rgb_set_state(struct led_state *state)
312 switch (state->type) {
314 case LED_TYPE_MANUAL:
317 _E("Not suppoted type (%d)", state->type);
322 if (GET_TYPE(state->color) == 0)
323 return gpio_rgb_turn_off(state);
325 return gpio_rgb_turn_on(state);
328 static int led_open(struct hw_info *info,
329 const char *id, struct hw_common **common)
331 struct led_device *led_dev;
334 if (!info || !id || !common)
337 led_dev = calloc(1, sizeof(struct led_device));
341 led_dev->common.info = info;
343 len = strlen(id) + 1;
344 if (!strncmp(id, LED_ID_NOTIFICATION, len)) {
345 if (gpio_rgb_init_led()) {
349 led_dev->set_state = gpio_rgb_set_state;
356 *common = (struct hw_common *)led_dev;
360 static int led_close(struct hw_common *common)
369 HARDWARE_MODULE_STRUCTURE = {
370 .magic = HARDWARE_INFO_TAG,
371 .hal_version = HARDWARE_INFO_VERSION,
372 .device_version = LED_HARDWARE_DEVICE_VERSION,
373 .id = LED_HARDWARE_DEVICE_ID,
374 .name = "I2C RGB LED",