Commit 30d3c071 authored by John W. Linville's avatar John W. Linville

Merge branch 'for-upstream' of...

Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
parents 330bd4ec 565766b0
...@@ -152,6 +152,7 @@ F: drivers/scsi/53c700* ...@@ -152,6 +152,7 @@ F: drivers/scsi/53c700*
6LOWPAN GENERIC (BTLE/IEEE 802.15.4) 6LOWPAN GENERIC (BTLE/IEEE 802.15.4)
M: Alexander Aring <alex.aring@gmail.com> M: Alexander Aring <alex.aring@gmail.com>
M: Jukka Rissanen <jukka.rissanen@linux.intel.com>
L: linux-bluetooth@vger.kernel.org L: linux-bluetooth@vger.kernel.org
L: linux-wpan@vger.kernel.org L: linux-wpan@vger.kernel.org
S: Maintained S: Maintained
......
This diff is collapsed.
...@@ -323,8 +323,8 @@ static int mrf24j40_read_rx_buf(struct mrf24j40 *devrec, ...@@ -323,8 +323,8 @@ static int mrf24j40_read_rx_buf(struct mrf24j40 *devrec,
#ifdef DEBUG #ifdef DEBUG
print_hex_dump(KERN_DEBUG, "mrf24j40 rx: ", print_hex_dump(KERN_DEBUG, "mrf24j40 rx: ",
DUMP_PREFIX_OFFSET, 16, 1, data, *len, 0); DUMP_PREFIX_OFFSET, 16, 1, data, *len, 0);
printk(KERN_DEBUG "mrf24j40 rx: lqi: %02hhx rssi: %02hhx\n", pr_debug("mrf24j40 rx: lqi: %02hhx rssi: %02hhx\n",
lqi_rssi[0], lqi_rssi[1]); lqi_rssi[0], lqi_rssi[1]);
#endif #endif
out: out:
...@@ -385,7 +385,7 @@ static int mrf24j40_tx(struct ieee802154_dev *dev, struct sk_buff *skb) ...@@ -385,7 +385,7 @@ static int mrf24j40_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
static int mrf24j40_ed(struct ieee802154_dev *dev, u8 *level) static int mrf24j40_ed(struct ieee802154_dev *dev, u8 *level)
{ {
/* TODO: */ /* TODO: */
printk(KERN_WARNING "mrf24j40: ed not implemented\n"); pr_warn("mrf24j40: ed not implemented\n");
*level = 0; *level = 0;
return 0; return 0;
} }
...@@ -412,6 +412,7 @@ static void mrf24j40_stop(struct ieee802154_dev *dev) ...@@ -412,6 +412,7 @@ static void mrf24j40_stop(struct ieee802154_dev *dev)
struct mrf24j40 *devrec = dev->priv; struct mrf24j40 *devrec = dev->priv;
u8 val; u8 val;
int ret; int ret;
dev_dbg(printdev(devrec), "stop\n"); dev_dbg(printdev(devrec), "stop\n");
ret = read_short_reg(devrec, REG_INTCON, &val); ret = read_short_reg(devrec, REG_INTCON, &val);
...@@ -419,8 +420,6 @@ static void mrf24j40_stop(struct ieee802154_dev *dev) ...@@ -419,8 +420,6 @@ static void mrf24j40_stop(struct ieee802154_dev *dev)
return; return;
val |= 0x1|0x8; /* Set TXNIE and RXIE. Disable Interrupts */ val |= 0x1|0x8; /* Set TXNIE and RXIE. Disable Interrupts */
write_short_reg(devrec, REG_INTCON, val); write_short_reg(devrec, REG_INTCON, val);
return;
} }
static int mrf24j40_set_channel(struct ieee802154_dev *dev, static int mrf24j40_set_channel(struct ieee802154_dev *dev,
...@@ -465,6 +464,7 @@ static int mrf24j40_filter(struct ieee802154_dev *dev, ...@@ -465,6 +464,7 @@ static int mrf24j40_filter(struct ieee802154_dev *dev,
if (changed & IEEE802515_AFILT_SADDR_CHANGED) { if (changed & IEEE802515_AFILT_SADDR_CHANGED) {
/* Short Addr */ /* Short Addr */
u8 addrh, addrl; u8 addrh, addrl;
addrh = le16_to_cpu(filt->short_addr) >> 8 & 0xff; addrh = le16_to_cpu(filt->short_addr) >> 8 & 0xff;
addrl = le16_to_cpu(filt->short_addr) & 0xff; addrl = le16_to_cpu(filt->short_addr) & 0xff;
...@@ -483,16 +483,17 @@ static int mrf24j40_filter(struct ieee802154_dev *dev, ...@@ -483,16 +483,17 @@ static int mrf24j40_filter(struct ieee802154_dev *dev,
write_short_reg(devrec, REG_EADR0 + i, addr[i]); write_short_reg(devrec, REG_EADR0 + i, addr[i]);
#ifdef DEBUG #ifdef DEBUG
printk(KERN_DEBUG "Set long addr to: "); pr_debug("Set long addr to: ");
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
printk("%02hhx ", addr[7 - i]); pr_debug("%02hhx ", addr[7 - i]);
printk(KERN_DEBUG "\n"); pr_debug("\n");
#endif #endif
} }
if (changed & IEEE802515_AFILT_PANID_CHANGED) { if (changed & IEEE802515_AFILT_PANID_CHANGED) {
/* PAN ID */ /* PAN ID */
u8 panidl, panidh; u8 panidl, panidh;
panidh = le16_to_cpu(filt->pan_id) >> 8 & 0xff; panidh = le16_to_cpu(filt->pan_id) >> 8 & 0xff;
panidl = le16_to_cpu(filt->pan_id) & 0xff; panidl = le16_to_cpu(filt->pan_id) & 0xff;
write_short_reg(devrec, REG_PANIDH, panidh); write_short_reg(devrec, REG_PANIDH, panidh);
...@@ -701,7 +702,7 @@ static int mrf24j40_probe(struct spi_device *spi) ...@@ -701,7 +702,7 @@ static int mrf24j40_probe(struct spi_device *spi)
int ret = -ENOMEM; int ret = -ENOMEM;
struct mrf24j40 *devrec; struct mrf24j40 *devrec;
printk(KERN_INFO "mrf24j40: probe(). IRQ: %d\n", spi->irq); dev_info(&spi->dev, "probe(). IRQ: %d\n", spi->irq);
devrec = devm_kzalloc(&spi->dev, sizeof(struct mrf24j40), GFP_KERNEL); devrec = devm_kzalloc(&spi->dev, sizeof(struct mrf24j40), GFP_KERNEL);
if (!devrec) if (!devrec)
......
...@@ -120,9 +120,9 @@ struct bt_voice { ...@@ -120,9 +120,9 @@ struct bt_voice {
#define BT_RCVMTU 13 #define BT_RCVMTU 13
__printf(1, 2) __printf(1, 2)
int bt_info(const char *fmt, ...); void bt_info(const char *fmt, ...);
__printf(1, 2) __printf(1, 2)
int bt_err(const char *fmt, ...); void bt_err(const char *fmt, ...);
#define BT_INFO(fmt, ...) bt_info(fmt "\n", ##__VA_ARGS__) #define BT_INFO(fmt, ...) bt_info(fmt "\n", ##__VA_ARGS__)
#define BT_ERR(fmt, ...) bt_err(fmt "\n", ##__VA_ARGS__) #define BT_ERR(fmt, ...) bt_err(fmt "\n", ##__VA_ARGS__)
...@@ -284,6 +284,7 @@ struct hci_req_ctrl { ...@@ -284,6 +284,7 @@ struct hci_req_ctrl {
struct bt_skb_cb { struct bt_skb_cb {
__u8 pkt_type; __u8 pkt_type;
__u8 incoming; __u8 incoming;
__u16 opcode;
__u16 expect; __u16 expect;
__u8 force_active; __u8 force_active;
struct l2cap_chan *chan; struct l2cap_chan *chan;
......
...@@ -385,6 +385,7 @@ enum { ...@@ -385,6 +385,7 @@ enum {
#define HCI_ERROR_AUTH_FAILURE 0x05 #define HCI_ERROR_AUTH_FAILURE 0x05
#define HCI_ERROR_MEMORY_EXCEEDED 0x07 #define HCI_ERROR_MEMORY_EXCEEDED 0x07
#define HCI_ERROR_CONNECTION_TIMEOUT 0x08 #define HCI_ERROR_CONNECTION_TIMEOUT 0x08
#define HCI_ERROR_REJ_LIMITED_RESOURCES 0x0d
#define HCI_ERROR_REJ_BAD_ADDR 0x0f #define HCI_ERROR_REJ_BAD_ADDR 0x0f
#define HCI_ERROR_REMOTE_USER_TERM 0x13 #define HCI_ERROR_REMOTE_USER_TERM 0x13
#define HCI_ERROR_REMOTE_LOW_RESOURCES 0x14 #define HCI_ERROR_REMOTE_LOW_RESOURCES 0x14
......
...@@ -926,7 +926,6 @@ int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); ...@@ -926,7 +926,6 @@ int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb); int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb);
int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count);
int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count); int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count);
void hci_init_sysfs(struct hci_dev *hdev); void hci_init_sysfs(struct hci_dev *hdev);
......
...@@ -709,8 +709,11 @@ EXPORT_SYMBOL_GPL(bt_debugfs); ...@@ -709,8 +709,11 @@ EXPORT_SYMBOL_GPL(bt_debugfs);
static int __init bt_init(void) static int __init bt_init(void)
{ {
struct sk_buff *skb;
int err; int err;
BUILD_BUG_ON(sizeof(struct bt_skb_cb) > sizeof(skb->cb));
BT_INFO("Core ver %s", VERSION); BT_INFO("Core ver %s", VERSION);
bt_debugfs = debugfs_create_dir("bluetooth", NULL); bt_debugfs = debugfs_create_dir("bluetooth", NULL);
......
...@@ -36,19 +36,25 @@ ...@@ -36,19 +36,25 @@
struct sco_param { struct sco_param {
u16 pkt_type; u16 pkt_type;
u16 max_latency; u16 max_latency;
u8 retrans_effort;
};
static const struct sco_param esco_param_cvsd[] = {
{ EDR_ESCO_MASK & ~ESCO_2EV3, 0x000a, 0x01 }, /* S3 */
{ EDR_ESCO_MASK & ~ESCO_2EV3, 0x0007, 0x01 }, /* S2 */
{ EDR_ESCO_MASK | ESCO_EV3, 0x0007, 0x01 }, /* S1 */
{ EDR_ESCO_MASK | ESCO_HV3, 0xffff, 0x01 }, /* D1 */
{ EDR_ESCO_MASK | ESCO_HV1, 0xffff, 0x01 }, /* D0 */
}; };
static const struct sco_param sco_param_cvsd[] = { static const struct sco_param sco_param_cvsd[] = {
{ EDR_ESCO_MASK & ~ESCO_2EV3, 0x000a }, /* S3 */ { EDR_ESCO_MASK | ESCO_HV3, 0xffff, 0xff }, /* D1 */
{ EDR_ESCO_MASK & ~ESCO_2EV3, 0x0007 }, /* S2 */ { EDR_ESCO_MASK | ESCO_HV1, 0xffff, 0xff }, /* D0 */
{ EDR_ESCO_MASK | ESCO_EV3, 0x0007 }, /* S1 */
{ EDR_ESCO_MASK | ESCO_HV3, 0xffff }, /* D1 */
{ EDR_ESCO_MASK | ESCO_HV1, 0xffff }, /* D0 */
}; };
static const struct sco_param sco_param_wideband[] = { static const struct sco_param esco_param_msbc[] = {
{ EDR_ESCO_MASK & ~ESCO_2EV3, 0x000d }, /* T2 */ { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000d, 0x02 }, /* T2 */
{ EDR_ESCO_MASK | ESCO_EV3, 0x0008 }, /* T1 */ { EDR_ESCO_MASK | ESCO_EV3, 0x0008, 0x02 }, /* T1 */
}; };
static void hci_le_create_connection_cancel(struct hci_conn *conn) static void hci_le_create_connection_cancel(struct hci_conn *conn)
...@@ -116,7 +122,7 @@ static void hci_reject_sco(struct hci_conn *conn) ...@@ -116,7 +122,7 @@ static void hci_reject_sco(struct hci_conn *conn)
{ {
struct hci_cp_reject_sync_conn_req cp; struct hci_cp_reject_sync_conn_req cp;
cp.reason = HCI_ERROR_REMOTE_USER_TERM; cp.reason = HCI_ERROR_REJ_LIMITED_RESOURCES;
bacpy(&cp.bdaddr, &conn->dst); bacpy(&cp.bdaddr, &conn->dst);
hci_send_cmd(conn->hdev, HCI_OP_REJECT_SYNC_CONN_REQ, sizeof(cp), &cp); hci_send_cmd(conn->hdev, HCI_OP_REJECT_SYNC_CONN_REQ, sizeof(cp), &cp);
...@@ -201,21 +207,26 @@ bool hci_setup_sync(struct hci_conn *conn, __u16 handle) ...@@ -201,21 +207,26 @@ bool hci_setup_sync(struct hci_conn *conn, __u16 handle)
switch (conn->setting & SCO_AIRMODE_MASK) { switch (conn->setting & SCO_AIRMODE_MASK) {
case SCO_AIRMODE_TRANSP: case SCO_AIRMODE_TRANSP:
if (conn->attempt > ARRAY_SIZE(sco_param_wideband)) if (conn->attempt > ARRAY_SIZE(esco_param_msbc))
return false; return false;
cp.retrans_effort = 0x02; param = &esco_param_msbc[conn->attempt - 1];
param = &sco_param_wideband[conn->attempt - 1];
break; break;
case SCO_AIRMODE_CVSD: case SCO_AIRMODE_CVSD:
if (conn->attempt > ARRAY_SIZE(sco_param_cvsd)) if (lmp_esco_capable(conn->link)) {
return false; if (conn->attempt > ARRAY_SIZE(esco_param_cvsd))
cp.retrans_effort = 0x01; return false;
param = &sco_param_cvsd[conn->attempt - 1]; param = &esco_param_cvsd[conn->attempt - 1];
} else {
if (conn->attempt > ARRAY_SIZE(sco_param_cvsd))
return false;
param = &sco_param_cvsd[conn->attempt - 1];
}
break; break;
default: default:
return false; return false;
} }
cp.retrans_effort = param->retrans_effort;
cp.pkt_type = __cpu_to_le16(param->pkt_type); cp.pkt_type = __cpu_to_le16(param->pkt_type);
cp.max_latency = __cpu_to_le16(param->max_latency); cp.max_latency = __cpu_to_le16(param->max_latency);
......
...@@ -4374,26 +4374,6 @@ static int hci_reassembly(struct hci_dev *hdev, int type, void *data, ...@@ -4374,26 +4374,6 @@ static int hci_reassembly(struct hci_dev *hdev, int type, void *data,
return remain; return remain;
} }
int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count)
{
int rem = 0;
if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT)
return -EILSEQ;
while (count) {
rem = hci_reassembly(hdev, type, data, count, type - 1);
if (rem < 0)
return rem;
data += (count - rem);
count = rem;
}
return rem;
}
EXPORT_SYMBOL(hci_recv_fragment);
#define STREAM_REASSEMBLY 0 #define STREAM_REASSEMBLY 0
int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count) int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count)
...@@ -4547,6 +4527,7 @@ static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, ...@@ -4547,6 +4527,7 @@ static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode,
BT_DBG("skb len %d", skb->len); BT_DBG("skb len %d", skb->len);
bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
bt_cb(skb)->opcode = opcode;
return skb; return skb;
} }
......
...@@ -135,40 +135,34 @@ int bt_to_errno(__u16 code) ...@@ -135,40 +135,34 @@ int bt_to_errno(__u16 code)
} }
EXPORT_SYMBOL(bt_to_errno); EXPORT_SYMBOL(bt_to_errno);
int bt_info(const char *format, ...) void bt_info(const char *format, ...)
{ {
struct va_format vaf; struct va_format vaf;
va_list args; va_list args;
int r;
va_start(args, format); va_start(args, format);
vaf.fmt = format; vaf.fmt = format;
vaf.va = &args; vaf.va = &args;
r = pr_info("%pV", &vaf); pr_info("%pV", &vaf);
va_end(args); va_end(args);
return r;
} }
EXPORT_SYMBOL(bt_info); EXPORT_SYMBOL(bt_info);
int bt_err(const char *format, ...) void bt_err(const char *format, ...)
{ {
struct va_format vaf; struct va_format vaf;
va_list args; va_list args;
int r;
va_start(args, format); va_start(args, format);
vaf.fmt = format; vaf.fmt = format;
vaf.va = &args; vaf.va = &args;
r = pr_err("%pV", &vaf); pr_err("%pV", &vaf);
va_end(args); va_end(args);
return r;
} }
EXPORT_SYMBOL(bt_err); EXPORT_SYMBOL(bt_err);
...@@ -494,8 +494,11 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, ...@@ -494,8 +494,11 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
} }
/* Not Just Works/Confirm results in MITM Authentication */ /* Not Just Works/Confirm results in MITM Authentication */
if (method != JUST_CFM) if (method != JUST_CFM) {
set_bit(SMP_FLAG_MITM_AUTH, &smp->flags); set_bit(SMP_FLAG_MITM_AUTH, &smp->flags);
if (hcon->pending_sec_level < BT_SECURITY_HIGH)
hcon->pending_sec_level = BT_SECURITY_HIGH;
}
/* If both devices have Keyoard-Display I/O, the master /* If both devices have Keyoard-Display I/O, the master
* Confirms and the slave Enters the passkey. * Confirms and the slave Enters the passkey.
......
...@@ -71,20 +71,42 @@ struct lowpan_dev_record { ...@@ -71,20 +71,42 @@ struct lowpan_dev_record {
struct list_head list; struct list_head list;
}; };
/* don't save pan id, it's intra pan */
struct lowpan_addr {
u8 mode;
union {
/* IPv6 needs big endian here */
__be64 extended_addr;
__be16 short_addr;
} u;
};
struct lowpan_addr_info {
struct lowpan_addr daddr;
struct lowpan_addr saddr;
};
static inline struct static inline struct
lowpan_dev_info *lowpan_dev_info(const struct net_device *dev) lowpan_dev_info *lowpan_dev_info(const struct net_device *dev)
{ {
return netdev_priv(dev); return netdev_priv(dev);
} }
static inline struct
lowpan_addr_info *lowpan_skb_priv(const struct sk_buff *skb)
{
WARN_ON_ONCE(skb_headroom(skb) < sizeof(struct lowpan_addr_info));
return (struct lowpan_addr_info *)(skb->data -
sizeof(struct lowpan_addr_info));
}
static int lowpan_header_create(struct sk_buff *skb, struct net_device *dev, static int lowpan_header_create(struct sk_buff *skb, struct net_device *dev,
unsigned short type, const void *_daddr, unsigned short type, const void *_daddr,
const void *_saddr, unsigned int len) const void *_saddr, unsigned int len)
{ {
const u8 *saddr = _saddr; const u8 *saddr = _saddr;
const u8 *daddr = _daddr; const u8 *daddr = _daddr;
struct ieee802154_addr sa, da; struct lowpan_addr_info *info;
struct ieee802154_mac_cb *cb = mac_cb_init(skb);
/* TODO: /* TODO:
* if this package isn't ipv6 one, where should it be routed? * if this package isn't ipv6 one, where should it be routed?
...@@ -98,41 +120,17 @@ static int lowpan_header_create(struct sk_buff *skb, struct net_device *dev, ...@@ -98,41 +120,17 @@ static int lowpan_header_create(struct sk_buff *skb, struct net_device *dev,
raw_dump_inline(__func__, "saddr", (unsigned char *)saddr, 8); raw_dump_inline(__func__, "saddr", (unsigned char *)saddr, 8);
raw_dump_inline(__func__, "daddr", (unsigned char *)daddr, 8); raw_dump_inline(__func__, "daddr", (unsigned char *)daddr, 8);
lowpan_header_compress(skb, dev, type, daddr, saddr, len); info = lowpan_skb_priv(skb);
/* NOTE1: I'm still unsure about the fact that compression and WPAN
* header are created here and not later in the xmit. So wait for
* an opinion of net maintainers.
*/
/* NOTE2: to be absolutely correct, we must derive PANid information
* from MAC subif of the 'dev' and 'real_dev' network devices, but
* this isn't implemented in mainline yet, so currently we assign 0xff
*/
cb->type = IEEE802154_FC_TYPE_DATA;
/* prepare wpan address data */
sa.mode = IEEE802154_ADDR_LONG;
sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
sa.extended_addr = ieee802154_devaddr_from_raw(saddr);
/* intra-PAN communications */
da.pan_id = sa.pan_id;
/* if the destination address is the broadcast address, use the
* corresponding short address
*/
if (lowpan_is_addr_broadcast(daddr)) {
da.mode = IEEE802154_ADDR_SHORT;
da.short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
} else {
da.mode = IEEE802154_ADDR_LONG;
da.extended_addr = ieee802154_devaddr_from_raw(daddr);
}
cb->ackreq = !lowpan_is_addr_broadcast(daddr); /* TODO: Currently we only support extended_addr */
info->daddr.mode = IEEE802154_ADDR_LONG;
memcpy(&info->daddr.u.extended_addr, daddr,
sizeof(info->daddr.u.extended_addr));
info->saddr.mode = IEEE802154_ADDR_LONG;
memcpy(&info->saddr.u.extended_addr, saddr,
sizeof(info->daddr.u.extended_addr));
return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev, return 0;
type, (void *)&da, (void *)&sa, 0);
} }
static int lowpan_give_skb_to_devices(struct sk_buff *skb, static int lowpan_give_skb_to_devices(struct sk_buff *skb,
...@@ -330,13 +328,68 @@ lowpan_xmit_fragmented(struct sk_buff *skb, struct net_device *dev, ...@@ -330,13 +328,68 @@ lowpan_xmit_fragmented(struct sk_buff *skb, struct net_device *dev,
return rc; return rc;
} }
static int lowpan_header(struct sk_buff *skb, struct net_device *dev)
{
struct ieee802154_addr sa, da;
struct ieee802154_mac_cb *cb = mac_cb_init(skb);
struct lowpan_addr_info info;
void *daddr, *saddr;
memcpy(&info, lowpan_skb_priv(skb), sizeof(info));
/* TODO: Currently we only support extended_addr */
daddr = &info.daddr.u.extended_addr;
saddr = &info.saddr.u.extended_addr;
lowpan_header_compress(skb, dev, ETH_P_IPV6, daddr, saddr, skb->len);
cb->type = IEEE802154_FC_TYPE_DATA;
/* prepare wpan address data */
sa.mode = IEEE802154_ADDR_LONG;
sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
sa.extended_addr = ieee802154_devaddr_from_raw(saddr);
/* intra-PAN communications */
da.pan_id = sa.pan_id;
/* if the destination address is the broadcast address, use the
* corresponding short address
*/
if (lowpan_is_addr_broadcast((const u8 *)daddr)) {
da.mode = IEEE802154_ADDR_SHORT;
da.short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
cb->ackreq = false;
} else {
da.mode = IEEE802154_ADDR_LONG;
da.extended_addr = ieee802154_devaddr_from_raw(daddr);
cb->ackreq = true;
}
return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev,
ETH_P_IPV6, (void *)&da, (void *)&sa, 0);
}
static netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev) static netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
struct ieee802154_hdr wpan_hdr; struct ieee802154_hdr wpan_hdr;
int max_single; int max_single, ret;
pr_debug("package xmit\n"); pr_debug("package xmit\n");
/* We must take a copy of the skb before we modify/replace the ipv6
* header as the header could be used elsewhere
*/
skb = skb_unshare(skb, GFP_ATOMIC);
if (!skb)
return NET_XMIT_DROP;
ret = lowpan_header(skb, dev);
if (ret < 0) {
kfree_skb(skb);
return NET_XMIT_DROP;
}
if (ieee802154_hdr_peek(skb, &wpan_hdr) < 0) { if (ieee802154_hdr_peek(skb, &wpan_hdr) < 0) {
kfree_skb(skb); kfree_skb(skb);
return NET_XMIT_DROP; return NET_XMIT_DROP;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment