| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-05-08 chenyong first version
- */
- #include <stdlib.h>
- #include <string.h>
- #include <at_device.h>
- #define DBG_TAG "at.dev"
- #define DBG_LVL DBG_INFO
- #include <rtdbg.h>
- /* The global list of at device */
- static rt_slist_t at_device_list = RT_SLIST_OBJECT_INIT(at_device_list);
- /* The global list of at device class */
- static rt_slist_t at_device_class_list = RT_SLIST_OBJECT_INIT(at_device_class_list);
- /**
- * This function will get the first initialized AT device.
- *
- * @return the AT device structure pointer
- */
- struct at_device *at_device_get_first_initialized(void)
- {
- rt_base_t level;
- rt_slist_t *node = RT_NULL;
- struct at_device *device = RT_NULL;
- level = rt_hw_interrupt_disable();
- rt_slist_for_each(node, &at_device_list)
- {
- device = rt_slist_entry(node, struct at_device, list);
- if (device && device->is_init == RT_TRUE)
- {
- rt_hw_interrupt_enable(level);
- return device;
- }
- }
- rt_hw_interrupt_enable(level);
- return RT_NULL;
- }
- /**
- * This function will get AT device by device name.
- *
- * @param type the name type
- * @param name the device name or the client name
- *
- * @return the AT device structure pointer
- */
- struct at_device *at_device_get_by_name(int type, const char *name)
- {
- rt_base_t level;
- rt_slist_t *node = RT_NULL;
- struct at_device *device = RT_NULL;
- RT_ASSERT(name);
- level = rt_hw_interrupt_disable();
- rt_slist_for_each(node, &at_device_list)
- {
- device = rt_slist_entry(node, struct at_device, list);
- if (device)
- {
- if (((type == AT_DEVICE_NAMETYPE_DEVICE) || (type == AT_DEVICE_NAMETYPE_NETDEV)) &&
- (rt_strncmp(device->name, name, rt_strlen(name)) == 0))
- {
- rt_hw_interrupt_enable(level);
- return device;
- }
- else if ((type == AT_DEVICE_NAMETYPE_CLIENT) &&
- (rt_strncmp(device->client->device->parent.name, name, rt_strlen(name)) == 0))
- {
- rt_hw_interrupt_enable(level);
- return device;
- }
- }
- }
- rt_hw_interrupt_enable(level);
- return RT_NULL;
- }
- #ifdef AT_USING_SOCKET
- /**
- * This function will get AT device by ip address.
- *
- * @param ip_addr input ip address
- * network
- * @return != NULL: network interface device object
- * NULL: get failed
- */
- struct at_device *at_device_get_by_ipaddr(ip_addr_t *ip_addr)
- {
- rt_base_t level;
- rt_slist_t *node = RT_NULL;
- struct at_device *device = RT_NULL;
- level = rt_hw_interrupt_disable();
- rt_slist_for_each(node, &at_device_list)
- {
- device = rt_slist_entry(node, struct at_device, list);
- if (device && ip_addr_cmp(ip_addr, &(device->netdev->ip_addr)))
- {
- rt_hw_interrupt_enable(level);
- return device;
- }
- }
- rt_hw_interrupt_enable(level);
- return RT_NULL;
- }
- #endif /* AT_USING_SOCKET */
- /**
- * This function will perform a variety of control functions on AT devices.
- *
- * @param device the pointer of AT device structure
- * @param cmd the command sent to AT device
- * @param arg the argument of command
- *
- * @return = 0: perform successfully
- * < 0: perform failed
- */
- int at_device_control(struct at_device *device, int cmd, void *arg)
- {
- if (device->class->device_ops->control)
- {
- return device->class->device_ops->control(device, cmd, arg);
- }
- else
- {
- LOG_W("AT device(%s) not support control operations.", device->name);
- return RT_EOK;
- }
- }
- /**
- * This function registers an AT device class with specified device class ID.
- *
- * @param class the pointer of AT device class structure
- * @param class_id AT device class ID
- *
- * @return 0: register successfully
- */
- int at_device_class_register(struct at_device_class *class, uint16_t class_id)
- {
- rt_base_t level;
- RT_ASSERT(class);
- /* Fill AT device class */
- class->class_id = class_id;
- /* Initialize current AT device class single list */
- rt_slist_init(&(class->list));
- level = rt_hw_interrupt_disable();
- /* Add current AT device class to list */
- rt_slist_append(&at_device_class_list, &(class->list));
- rt_hw_interrupt_enable(level);
- return RT_EOK;
- }
- /* Get AT device class by client ID */
- static struct at_device_class *at_device_class_get(uint16_t class_id)
- {
- rt_base_t level;
- rt_slist_t *node = RT_NULL;
- struct at_device_class *class = RT_NULL;
- level = rt_hw_interrupt_disable();
- /* Get AT device class by class ID */
- rt_slist_for_each(node, &at_device_class_list)
- {
- class = rt_slist_entry(node, struct at_device_class, list);
- if (class && class->class_id == class_id)
- {
- rt_hw_interrupt_enable(level);
- return class;
- }
- }
- rt_hw_interrupt_enable(level);
- return RT_NULL;
- }
- /**
- * This function registers an AT device with specified device name and AT client name.
- *
- * @param device the pointer of AT device structure
- * @param device_name AT device name
- * @param at_client_name AT device client name
- * @param class_id AT device class ID
- * @param user_data user-specific data
- *
- * @return = 0: register successfully
- * < 0: register failed
- */
- int at_device_register(struct at_device *device, const char *device_name,
- const char *at_client_name, uint16_t class_id, void *user_data)
- {
- rt_base_t level;
- int result = 0;
- static int device_counts = 0;
- char name[RT_NAME_MAX] = {0};
- struct at_device_class *class = RT_NULL;
- RT_ASSERT(device);
- RT_ASSERT(device_name);
- RT_ASSERT(at_client_name);
- class = at_device_class_get(class_id);
- if (class == RT_NULL)
- {
- LOG_E("get AT device class(%d) failed.", class_id);
- result = -RT_ERROR;
- goto __exit;
- }
- /* Fill AT device object*/
- #ifdef AT_USING_SOCKET
- device->sockets = (struct at_socket *) rt_calloc(class->socket_num, sizeof(struct at_socket));
- if (device->sockets == RT_NULL)
- {
- LOG_E("no memory for AT Socket number(%d) create.", class->socket_num);
- result = -RT_ENOMEM;
- goto __exit;
- }
- /* create AT device socket event */
- rt_snprintf(name, RT_NAME_MAX, "at_se%d", device_counts++);
- device->socket_event = rt_event_create(name, RT_IPC_FLAG_FIFO);
- if (device->socket_event == RT_NULL)
- {
- LOG_E("no memory for AT device(%s) socket event create.", device_name);
- result = -RT_ENOMEM;
- goto __exit;
- }
- #endif /* AT_USING_SOCKET */
- rt_memcpy(device->name, device_name, rt_strlen(device_name));
- device->class = class;
- device->user_data = user_data;
- /* Initialize current AT device single list */
- rt_slist_init(&(device->list));
- level = rt_hw_interrupt_disable();
- /* Add current AT device to device list */
- rt_slist_append(&at_device_list, &(device->list));
- rt_hw_interrupt_enable(level);
- /* Initialize AT device */
- result = class->device_ops->init(device);
- if (result < 0)
- {
- goto __exit;
- }
- __exit:
- if (result < 0)
- {
- device->is_init = RT_FALSE;
- }
- else
- {
- device->is_init = RT_TRUE;
- }
- return result;
- }
|