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 peripheral_i2c_write_byte(handle, STOP_SCRIPT_CMD);
82 static void blinkm_led_off(peripheral_i2c_h handle)
84 peripheral_i2c_write(handle, off_cmd, sizeof(off_cmd));
87 static void blinkm_led_init(peripheral_i2c_h handle)
89 blinkm_led_stop_script(handle);
90 blinkm_led_off(handle);
93 static void blinkm_led_set_color(peripheral_i2c_h handle, uint8_t *pkt_data, int len)
95 peripheral_i2c_write(handle, pkt_data, len);
98 static int gpio_led_open_device(int device_index, peripheral_i2c_h *device_handle)
102 if ((ret = peripheral_i2c_open(device_index, BLINKM_DEFAULT_ADDR, device_handle)) < PERIPHERAL_ERROR_NONE) {
103 _E("Failed to open I2C");
108 static int gpio_led_close_device(peripheral_i2c_h device_handle)
112 if ((ret = peripheral_i2c_close(device_handle)) < PERIPHERAL_ERROR_NONE) {
113 _E("Failed to close I2C");
118 static int gpio_rgb_set_brightness(struct led_state *state)
120 uint8_t cmd_pkt[4] = { SET_CMD_CODE, };
121 peripheral_i2c_h handle;
128 color = state->color;
130 cmd_pkt[1] = GET_RED_BRT(color);
131 cmd_pkt[2] = GET_GREEN_BRT(color);
132 cmd_pkt[3] = GET_BLUE_BRT(color);
134 _I("COLOR(%x) r(%x), g(%x), b(%x)", color, cmd_pkt[1], cmd_pkt[2], cmd_pkt[3]);
136 if ((ret = gpio_led_open_device(GPIO_I2C_BUS_INDEX, &handle)) < PERIPHERAL_ERROR_NONE)
139 blinkm_led_set_color(handle, cmd_pkt, sizeof(cmd_pkt));
141 if ((ret = gpio_led_close_device(handle)) < PERIPHERAL_ERROR_NONE)
148 static int gpio_rgb_turn_off(struct led_state *state)
150 struct led_state st = { LED_TYPE_MANUAL, };
151 return gpio_rgb_set_brightness(&st);
154 /* release play list */
155 static void free_func(gpointer data)
157 struct gpio_rgb_play_color_info *color = data;
161 static void release_play_info(void)
163 if (play_info.play_list) {
164 g_list_free_full(play_info.play_list, free_func);
165 play_info.play_list = NULL;
167 play_info.nr_play = 0;
169 if (play_info.timer) {
170 g_source_remove(play_info.timer);
174 gpio_rgb_turn_off(NULL);
177 static int gpio_rgb_init_led()
179 peripheral_i2c_h handle;
182 if ((ret = gpio_led_open_device(GPIO_I2C_BUS_INDEX, &handle)) < PERIPHERAL_ERROR_NONE)
185 blinkm_led_init(handle);
187 if ((ret = gpio_led_close_device(handle)) < PERIPHERAL_ERROR_NONE)
193 /* timer callback to change colors which are stored in play_list */
194 static gboolean gpio_rgb_timer_expired(gpointer data)
196 struct gpio_rgb_play_color_info *color;
197 struct led_state state = {LED_TYPE_MANUAL, };
200 if (play_info.timer) {
201 g_source_remove(play_info.timer);
205 color = g_list_nth_data(play_info.play_list, play_info.index);
207 _E("Failed to get (%d)th item from the play list", play_info.index);
211 play_info.timer = g_timeout_add(color->time, gpio_rgb_timer_expired, data);
212 if (play_info.timer == 0) {
213 _E("Failed to add timeout for LED blinking");
217 state.color = color->color;
219 ret = gpio_rgb_set_brightness(&state);
221 _E("Failed to set brightness (%d)", ret);
226 if (play_info.index == play_info.nr_play)
229 return G_SOURCE_CONTINUE;
234 return G_SOURCE_REMOVE;
237 /* insert color info to the play_list */
238 static int gpio_rgb_insert_play_list(unsigned color, int on, int off)
240 struct gpio_rgb_play_color_info *on_info, *off_info;
244 on_info = calloc(1, sizeof(struct gpio_rgb_play_color_info));
247 off_info = calloc(1, sizeof(struct gpio_rgb_play_color_info));
253 on_info->color = color;
255 play_info.play_list = g_list_append(play_info.play_list, on_info);
258 off_info->time = off;
259 play_info.play_list = g_list_append(play_info.play_list, off_info);
264 /* insert color info to the play list and start to play */
265 static int gpio_rgb_set_brightness_blink(struct led_state *state)
270 val = GET_RED_ONLY(state->color);
272 ret = gpio_rgb_insert_play_list(val, state->duty_on, state->duty_off);
274 _E("Failed to insert color info to list (%d)", ret);
276 val = GET_GREEN_ONLY(state->color);
278 ret = gpio_rgb_insert_play_list(val, state->duty_on, state->duty_off);
280 _E("Failed to insert color info to list (%d)", ret);
282 val = GET_BLUE_ONLY(state->color);
284 ret = gpio_rgb_insert_play_list(val, state->duty_on, state->duty_off);
286 _E("Failed to insert color info to list (%d)", ret);
289 play_info.nr_play = g_list_length(play_info.play_list);
292 gpio_rgb_timer_expired(NULL);
296 static int gpio_rgb_turn_on(struct led_state *state)
298 if (state->type == LED_TYPE_MANUAL)
299 return gpio_rgb_set_brightness(state);
301 return gpio_rgb_set_brightness_blink(state);
304 static int gpio_rgb_set_state(struct led_state *state)
309 switch (state->type) {
311 case LED_TYPE_MANUAL:
314 _E("Not suppoted type (%d)", state->type);
319 if (GET_TYPE(state->color) == 0)
320 return gpio_rgb_turn_off(state);
322 return gpio_rgb_turn_on(state);
325 static int led_open(struct hw_info *info,
326 const char *id, struct hw_common **common)
328 struct led_device *led_dev;
331 if (!info || !id || !common)
334 led_dev = calloc(1, sizeof(struct led_device));
338 led_dev->common.info = info;
340 len = strlen(id) + 1;
341 if (!strncmp(id, LED_ID_NOTIFICATION, len)) {
342 if (gpio_rgb_init_led()) {
346 led_dev->set_state = gpio_rgb_set_state;
353 *common = (struct hw_common *)led_dev;
357 static int led_close(struct hw_common *common)
366 HARDWARE_MODULE_STRUCTURE = {
367 .magic = HARDWARE_INFO_TAG,
368 .hal_version = HARDWARE_INFO_VERSION,
369 .device_version = LED_HARDWARE_DEVICE_VERSION,
370 .id = LED_HARDWARE_DEVICE_ID,
371 .name = "I2C RGB LED",