📄 irlan_common.c
字号:
irlan_ctrl_data_request(self, skb);}/* * Function irlan_set_multicast_filter (self, status) * * Make IrLAN provider accept ethernet frames addressed to the multicast * address. * */void irlan_set_multicast_filter(struct irlan_cb *self, int status){ struct sk_buff *skb; __u8 *frame; IRDA_DEBUG(2, "%s()\n", __FUNCTION__ ); IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;); skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER + IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") + IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "MULTICAST") + /* We may waste one byte here...*/ IRLAN_STRING_PARAMETER_LEN("FILTER_MODE", "NONE"), GFP_ATOMIC); if (!skb) return; /* Reserve space for TTP, LMP, and LAP header */ skb_reserve(skb, self->client.max_header_size); skb_put(skb, 2); frame = skb->data; frame[0] = CMD_FILTER_OPERATION; frame[1] = 0x03; /* Three parameters */ irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data); irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST"); if (status) irlan_insert_string_param(skb, "FILTER_MODE", "ALL"); else irlan_insert_string_param(skb, "FILTER_MODE", "NONE"); irlan_ctrl_data_request(self, skb);}/* * Function irlan_get_unicast_addr (self) * * Retrieves the unicast address from the IrLAN provider. This address * will be inserted into the devices structure, so the ethernet layer * can construct its packets. * */static void irlan_get_unicast_addr(struct irlan_cb *self){ struct sk_buff *skb; __u8 *frame; IRDA_DEBUG(2, "%s()\n", __FUNCTION__ ); IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;); skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER + IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") + IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "DIRECTED") + IRLAN_STRING_PARAMETER_LEN("FILTER_OPERATION", "DYNAMIC"), GFP_ATOMIC); if (!skb) return; /* Reserve space for TTP, LMP, and LAP header */ skb_reserve(skb, self->client.max_header_size); skb_put(skb, 2); frame = skb->data; frame[0] = CMD_FILTER_OPERATION; frame[1] = 0x03; /* Three parameters */ irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data); irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED"); irlan_insert_string_param(skb, "FILTER_OPERATION", "DYNAMIC"); irlan_ctrl_data_request(self, skb);}/* * Function irlan_get_media_char (self) * * * */void irlan_get_media_char(struct irlan_cb *self){ struct sk_buff *skb; __u8 *frame; IRDA_DEBUG(4, "%s()\n", __FUNCTION__ ); IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;); skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER + IRLAN_STRING_PARAMETER_LEN("MEDIA", "802.3"), GFP_ATOMIC); if (!skb) return; /* Reserve space for TTP, LMP, and LAP header */ skb_reserve(skb, self->client.max_header_size); skb_put(skb, 2); frame = skb->data; /* Build frame */ frame[0] = CMD_GET_MEDIA_CHAR; frame[1] = 0x01; /* One parameter */ irlan_insert_string_param(skb, "MEDIA", "802.3"); irlan_ctrl_data_request(self, skb);}/* * Function insert_byte_param (skb, param, value) * * Insert byte parameter into frame * */int irlan_insert_byte_param(struct sk_buff *skb, char *param, __u8 value){ return __irlan_insert_param(skb, param, IRLAN_BYTE, value, 0, NULL, 0);}int irlan_insert_short_param(struct sk_buff *skb, char *param, __u16 value){ return __irlan_insert_param(skb, param, IRLAN_SHORT, 0, value, NULL, 0);}/* * Function insert_string (skb, param, value) * * Insert string parameter into frame * */int irlan_insert_string_param(struct sk_buff *skb, char *param, char *string){ int string_len = strlen(string); return __irlan_insert_param(skb, param, IRLAN_ARRAY, 0, 0, string, string_len);}/* * Function insert_array_param(skb, param, value, len_value) * * Insert array parameter into frame * */int irlan_insert_array_param(struct sk_buff *skb, char *name, __u8 *array, __u16 array_len){ return __irlan_insert_param(skb, name, IRLAN_ARRAY, 0, 0, array, array_len);}/* * Function insert_param (skb, param, value, byte) * * Insert parameter at end of buffer, structure of a parameter is: * * ----------------------------------------------------------------------- * | Name Length[1] | Param Name[1..255] | Val Length[2] | Value[0..1016]| * ----------------------------------------------------------------------- */static int __irlan_insert_param(struct sk_buff *skb, char *param, int type, __u8 value_byte, __u16 value_short, __u8 *value_array, __u16 value_len){ __u8 *frame; __u8 param_len; __le16 tmp_le; /* Temporary value in little endian format */ int n=0; if (skb == NULL) { IRDA_DEBUG(2, "%s(), Got NULL skb\n", __FUNCTION__ ); return 0; } param_len = strlen(param); switch (type) { case IRLAN_BYTE: value_len = 1; break; case IRLAN_SHORT: value_len = 2; break; case IRLAN_ARRAY: IRDA_ASSERT(value_array != NULL, return 0;); IRDA_ASSERT(value_len > 0, return 0;); break; default: IRDA_DEBUG(2, "%s(), Unknown parameter type!\n", __FUNCTION__ ); return 0; break; } /* Insert at end of sk-buffer */ frame = skb_tail_pointer(skb); /* Make space for data */ if (skb_tailroom(skb) < (param_len+value_len+3)) { IRDA_DEBUG(2, "%s(), No more space at end of skb\n", __FUNCTION__ ); return 0; } skb_put(skb, param_len+value_len+3); /* Insert parameter length */ frame[n++] = param_len; /* Insert parameter */ memcpy(frame+n, param, param_len); n += param_len; /* Insert value length (2 byte little endian format, LSB first) */ tmp_le = cpu_to_le16(value_len); memcpy(frame+n, &tmp_le, 2); n += 2; /* To avoid alignment problems */ /* Insert value */ switch (type) { case IRLAN_BYTE: frame[n++] = value_byte; break; case IRLAN_SHORT: tmp_le = cpu_to_le16(value_short); memcpy(frame+n, &tmp_le, 2); n += 2; break; case IRLAN_ARRAY: memcpy(frame+n, value_array, value_len); n+=value_len; break; default: break; } IRDA_ASSERT(n == (param_len+value_len+3), return 0;); return param_len+value_len+3;}/* * Function irlan_extract_param (buf, name, value, len) * * Extracts a single parameter name/value pair from buffer and updates * the buffer pointer to point to the next name/value pair. */int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len){ __u8 name_len; __u16 val_len; int n=0; IRDA_DEBUG(4, "%s()\n", __FUNCTION__ ); /* get length of parameter name (1 byte) */ name_len = buf[n++]; if (name_len > 254) { IRDA_DEBUG(2, "%s(), name_len > 254\n", __FUNCTION__ ); return -RSP_INVALID_COMMAND_FORMAT; } /* get parameter name */ memcpy(name, buf+n, name_len); name[name_len] = '\0'; n+=name_len; /* * Get length of parameter value (2 bytes in little endian * format) */ memcpy(&val_len, buf+n, 2); /* To avoid alignment problems */ le16_to_cpus(&val_len); n+=2; if (val_len > 1016) { IRDA_DEBUG(2, "%s(), parameter length to long\n", __FUNCTION__ ); return -RSP_INVALID_COMMAND_FORMAT; } *len = val_len; /* get parameter value */ memcpy(value, buf+n, val_len); value[val_len] = '\0'; n+=val_len; IRDA_DEBUG(4, "Parameter: %s ", name); IRDA_DEBUG(4, "Value: %s\n", value); return n;}#ifdef CONFIG_PROC_FS/* * Start of reading /proc entries. * Return entry at pos, * or start_token to indicate print header line * or NULL if end of file */static void *irlan_seq_start(struct seq_file *seq, loff_t *pos){ int i = 1; struct irlan_cb *self; rcu_read_lock(); if (*pos == 0) return SEQ_START_TOKEN; list_for_each_entry(self, &irlans, dev_list) { if (*pos == i) return self; ++i; } return NULL;}/* Return entry after v, and increment pos */static void *irlan_seq_next(struct seq_file *seq, void *v, loff_t *pos){ struct list_head *nxt; ++*pos; if (v == SEQ_START_TOKEN) nxt = irlans.next; else nxt = ((struct irlan_cb *)v)->dev_list.next; return (nxt == &irlans) ? NULL : list_entry(nxt, struct irlan_cb, dev_list);}/* End of reading /proc file */static void irlan_seq_stop(struct seq_file *seq, void *v){ rcu_read_unlock();}/* * Show one entry in /proc file. */static int irlan_seq_show(struct seq_file *seq, void *v){ if (v == SEQ_START_TOKEN) seq_puts(seq, "IrLAN instances:\n"); else { struct irlan_cb *self = v; IRDA_ASSERT(self != NULL, return -1;); IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;); seq_printf(seq,"ifname: %s,\n", self->dev->name); seq_printf(seq,"client state: %s, ", irlan_state[ self->client.state]); seq_printf(seq,"provider state: %s,\n", irlan_state[ self->provider.state]); seq_printf(seq,"saddr: %#08x, ", self->saddr); seq_printf(seq,"daddr: %#08x\n", self->daddr); seq_printf(seq,"version: %d.%d,\n", self->version[1], self->version[0]); seq_printf(seq,"access type: %s\n", irlan_access[self->client.access_type]); seq_printf(seq,"media: %s\n", irlan_media[self->media]); seq_printf(seq,"local filter:\n"); seq_printf(seq,"remote filter: "); irlan_print_filter(seq, self->client.filter_type); seq_printf(seq,"tx busy: %s\n", netif_queue_stopped(self->dev) ? "TRUE" : "FALSE"); seq_putc(seq,'\n'); } return 0;}static const struct seq_operations irlan_seq_ops = { .start = irlan_seq_start, .next = irlan_seq_next, .stop = irlan_seq_stop, .show = irlan_seq_show,};static int irlan_seq_open(struct inode *inode, struct file *file){ return seq_open(file, &irlan_seq_ops);}#endifMODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");MODULE_DESCRIPTION("The Linux IrDA LAN protocol");MODULE_LICENSE("GPL");module_param(eth, bool, 0);MODULE_PARM_DESC(eth, "Name devices ethX (0) or irlanX (1)");module_param(access, int, 0);MODULE_PARM_DESC(access, "Access type DIRECT=1, PEER=2, HOSTED=3");module_init(irlan_init);module_exit(irlan_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -